文章
问答
冒泡
ES6~ES11新增特性合集

ES6

  • let 和 const
区别1:var声明的变量会挂载在window上,而let和const声明的变量不会
区别2:var声明的变量存在变量提升,而let和const不存在变量提升
区别3:let和const声明形成快作用域
区别4:同一作用域下的let和const不能声明同名变量,而var可以
  • 字符串方法和模板字符串
// 模板字符串
const name = 'mySkey'
const str = `my name is ${name}`

// startsWith 判定字符串是否以另一个字符串开头,返回布尔值
console.log('hello wolrd'.startsWith('hello'))	// true

// endsWith	判定字符串是否以另一个字符串结尾,返回布尔值
console.log('hello wolrd'.endsWith('hello'))	// false

// includes	判定字符串是否以包含另一个字符串,返回布尔值
console.log('hello wolrd'.includes('hello'))	// true

// repeat 将字符串复制多次,参数就是被复制的次数
console.log('hello wolrd'.repeat(2))	// hello wolrdhello wolrd
  • 解构赋值
//数组
let [a, b, c] =[1, 2, 3]
//对象
let{ a, b, c} = { a: 1, b: 2, c: 3}
  • 数组方法
// Array.of 解决了Array在接收参数时的BUG
console.log(Array.of(3)) // [3]

// Array.from 将类数组对象转为数组,ES6之前,我们可以通过[].slice.call(arr)方式转为数组
console.log(Array.from(new Set([1, 2, 3])))
  • 对象两个方法 is 和 assign
// Object.is 用于比较两者是否全等
console.log(NaN === NaN) //false
console.log(Object.is(NaN,NaN)) //true
console.log(+0 === -0) // true
console.log(Object.is(+0, -0)) // false

// Object.assign 用于对象属性的复制(浅复制)
var obj = {}
var obj1 = {sex :'女'}
Object.assign(obj, obj1)
  • 箭头函数

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

// 一个参数时,可以不用()包含形参; 一句执行语句时,可以不用{}包含代码块; 一行代码时是有返回值的。
let fn = num=>console.log(num)

// 两个参数
let fn = (a,b)=>a+b

// 箭头函数中的this
function foo() {
    setTimeout(() => {
        console.log('id:', this.id);
    }, 100);
}

var id = 21;

foo.call({ id: 42 }); // id: 42
//
foo::bar;
// 等同于
bar.bind(foo);

foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);
  • Proxy

ES6中增加了一个Proxy代理类,他可以对指定的对象的访问操作和修改操作进行拦截,vue2.0是通过Object.defineProperty来拦截,要是开启深层拦截将很耗费性能,所以对于对象,数组的更改,无法数据动态响应;在vue3.0中将使用Proxy来进行拦截,将解决这一问题。

var proxy = new Proxy(原对象,{
    get:function(原对象,属性名){},
    set:function(原对象,属性名,属性值){},
})
  • Set和 WeakSet

Set 它类似于数组,但是成员的值都是唯一的,没有重复的值,使用场景并不多,但是用来做数组去重很方便
WeakSet 与 Set 有两个区别。1、WeakSet 的成员只能是对象 2、WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中

// 数组去重
let removeSame = arr => [...new Set(arr)]

// 也可以用于字符串去重
let removeSameStr = str => [...new Set(str)].join('')

// WeakSet
const a = [[1, 2], [3, 4]];
const ws = new WeakSet(a);
// WeakSet {[1, 2], [3, 4]}
  • Map 和 WeakMap

JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。
WeakMap 结构与Map结构类似,也是用于生成键值对的集合。WeakMap与Map的区别有两点:1、WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名 2、WeakMap的键名所指向的对象,不计入垃圾回收机制

const map = new Map([
    ['name', '张三'],
    ['title', 'Author']
]);

map.size // 2
map.has('name') // true
map.get('name') // "张三"
map.has('title') // true
map.get('title') // "Author"

// WeakMap
const wm = new WeakMap();
let key = {};
let obj = {foo: 1};

wm.set(key, obj);
obj = null;
wm.get(key)
// Object {foo: 1}
  • Symbol
let mySymbol = Symbol();

// 第一种写法
let a = {};
a[mySymbol] = 'Hello!';

// 第二种写法
let a = {
[mySymbol]: 'Hello!'
};

// 第三种写法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });

// 以上写法都得到同样结果
a[mySymbol] // "Hello!"
  • Promise

Promise是es6用来处理异步的对象,分为三种状态:pending、fulfilled、rejected。对象拥有resolve和reject两个方法,分别在里面处理正确情况和异常情况。

let getData = ()=>{
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            let data = { code: 404, msg: 'I am sleeping' }
            try{
                // throw('我非要出个错,来看一下catch有没有用')
                // throw 强制产生一个错误,Promis的catch就能捕获到错误
                resolve(data)
            }catch(err){
                reject(err)
            }
        }, 3000)
    })
}

// 调用函数,在函数返回时使用数据
getData().then(res=>{
    console.log('后台说:' + res.msg)
}).catch(err=>{
    console.log('发生的错误是:' + err)
})
  • Generator

Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。在node的中间件中使用广泛,中间件授权之类,vue的路由鉴权也有使用

let getData = ()=>{
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            let data = { code: 404, msg: 'I am sleeping' }
            resolve(data)
        }, 3000)
    })
}

// 调用函数,在函数返回时使用数据
(function * () {
    let data = yield getData();
    return data;
})().next().value.then(res=>{
    console.log(res)
})
  • Iterator 和 for...of循环

for...of 和 for...in 区别在于 for...in会循环原型链 性能差
具有Symbol.iterator属性可以使用for...of
JavaScript 原有的表示“集合”的数据结构,主要是数组(Array)和对象(Object),ES6 又添加了Map和Set。这样就有了四种数据集合,用户还可以组合使用它们,定义自己的数据结构,比如数组的成员是Map,Map的成员是对象。这样就需要一种统一的接口机制,来处理所有不同的数据结构。
遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。遍历器可以直接遍历迭代器的结果,而不需要每次next

function* foo() {
    yield 1;
    yield 2;
    yield 3;
    yield 4;
    yield 5;
    return 6;
}

for (let v of foo()) {
    console.log(v);
}
// 1 2 3 4 5
  • Class

class的本质是function,它可以看做是一个语法糖,让对象原型的写法更加清晰,更像面向对象编程的写法

class Person {
    constructor(props, name, age){
        super(props);
        this.name = name;
        this.age = age;
    }
    sing(){
        console.log('sing');
    }
    cry(){
        console.log('cry');
    }
}

Person.prototype = {
    talk: function(){
    console.log('talk')
}
let mySkey = new Person('mySkey', 23)
mySkey.talk()
  • 模块化

ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。



ES7

  • Array.prototype.includes()
arr.includes(x)
// 相当于
arr.indexOf(x) >= 0
  • 指数操作符 **

在ES7中引入了指数运算符**,** 有与Math.pow(..)等效的计算结果。

console.log(2**10);// 输出1024

ES8

  • async/await

async,await异步解决方案:优化回调地狱,ES6中的promise解决了回调地狱,但是要连续打点调用then,就会显得不清楚,所以引入了async函数,awiat表达式

async function process(array) {
    for await (let i of array) {
        doSomething(i);
    }
}
  • Object.values()

Object.values()就是将对象的值合并到一个数组中, Object.keys() 是将对象的key合并到一个数组中

const obj = {a: 1, b: 2, c: 3};
console.log(Object.values(obj)) // [1, 2, 3]
  • Object.entries()和Object.fromEntries

Object.entries()函数返回一个给定对象自身可枚举属性的键值对的数组。

let obj = {a:1, b:2, c:3};
console.log(Object.entries(obj)) // [[a, 1], [b, 2],[c,3]]

const map = new Map([ ['foo', 'bar'], ['baz', 42] ]);
const obj = Object.fromEntries(map);
console.log(obj);
// { foo: "bar", baz: 42 }
const arr = [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ];
const obj = Object.fromEntries(arr);
console.log(obj);
// { 0: "a", 1: "b", 2: "c" }
  • string padStart() 和 padEnd

允许将空字符串或其他字符串添加到原始字符串的开头或结尾。

console.log('8'.padStart(2, '0')) arguments[0] => length

ES9

  • 异步迭代

在async/await的某些时刻,你可能尝试在同步循环中调用异步函数。例如:
// 以下两种方式就循环本身依旧保持同步

async function process(array) {
    for (let i of array) {
        await doSomething(i);
    }
}
async function process(array) {
    array.forEach(async i => {
        await doSomething(i);
    });
}

// 想要同步循环,需要以下写法
async function process(array) {
    for await (let i of array) {
        doSomething(i);
    }
}
  • Promise.finally()
function doSomething() {
    doSomething1()
    .then(doSomething2)
    .then(doSomething3)
    .catch(err => {
        console.log(err);
    })
    .finally(() => {
        // finish here!	// 清除loading之类的
    });
}

ES10

  • Array的flat()方法和flatMap()方法
// flat()方法最基本的作用就是数组降维
var arr3 = [[1,2,[3]],4,5,[6]]
arr3.flat(Infinity); /使用 Infinity 作为深度,展开任意深度的嵌套数组
// [1, 2, 3, 4, 5, 6]

// 可以利用flat()方法的特性来去除数组的空项
var arr4 = [1, 2, , 4, 5];
arr4.flat();
// [1, 2, 4, 5]
  • String的trimStart()方法和trimEnd()方法

分别是去除首位空白符的

ES11

  • Nullish coalescing Operator(空值处理)

如果表达式在 ?? 的左侧 运算符求值为undefined或null,返回其右侧。

let user = {
u1: 0,
u2: false,
u3: null,
u4: undefined
u5: '',
}
let u1 = user.u1 || '用户1' // 用户1
let u2 = user.u2 || '用户2' // 用户2
let u3 = user.u3 || '用户3' // 用户3
let u4 = user.u4 || '用户4' // 用户4
let u5 = user.u5 || '用户5' // 用户5
// es11语法
let u1 = user.u1 ?? '用户1' // 0
let u2 = user.u2 ?? '用户2' // false
let u3 = user.u3 ?? '用户3' // 用户3
let u4 = user.u4 ?? '用户4' // 用户4
let u5 = user.u5 ?? '用户5' // ''
  • Optional chaining(可选链)

?. 用户检测不确定的中间节点,如果不存在中间节点则返回undefined。避免了程序报错直接导致整个应用挂掉,可以用lodash的 get 来处理这种链路不确定性

let person = {}
let age = person.info.age
// TypeError: Cannot read property 'name' of undefined
// 因为person的info属性为undefined,那么直接就报错了
let age = person.info?.age
// undefined

使用lodash
import _ from 'lodash'
let age = _.get(person, 'person.info.age', '')
  • Promise.allSettled

使用 Promise.all 来并发两个接口,如果其中任意一个异常,则两个区域都无法正常渲染。Promise.allSettled 则可以避免这个问题

Promise.all([
    new Promise.reject('a1'),
    new Promise.resolve('a2')
]).then((ret) => {
    // 不会执行
    console.log(ret)
}).catch((error) => {
    // 因为有一个promise返回为reject。所以程序只会走到这里
    // 输出:a1
    console.log(error)
})

// 使用es11的Promise.allSettled
Promise.allSettled([
    new Promise.reject('a1'),
    new Promise.resolve('a2')
]).then((ret) => {
    // 输出
    // 0: {status: "fulfilled", value: "a1"},
    // 1: {status: "rejected", value: "a2"}
    console.log(ret)

    // 这样可以过滤掉rejected,避免整段程序运行错乱
    handleFun(ret.filter(el => el.status !== 'rejected'))
})
  • Dynamic import

动态引入,之前的import是静态引入

const util = './util.js'
import(util).then((module) => {
    module.fun1();
    module.fun2();
});

(async () => {
    const util = './util.js';
    const module = await import(util)
    const fun1 = module.fun1(1);
    const fun2 = module.fun1(2);
})();
  • BigInt

BigInt是第7个基本类型,它是一个任意精度的整数。变量可以代表2⁵³不仅是在9007199254740992处的最大值

// 创建方法一:在整数后面加 n
let bigInt = 9999999999999999n;
// 创建方法二:BigInt函数
let bigInt2 = BigInt(9999999999999999);
let bigInt3 = BigInt('9999999999999999');

// bigIng类型可以进行更大的值计算
let sum = bigInt + bigInt2 // 19999999999999999n
sum.toString() // 19999999999999999 使用toString可以去掉后面的n

// bigint是一种新的原始类型
typeof 9999999999999999n; // -> 'bigint
  • export * as ns from “mod”

这是对 ES 规范的有力补充,它允许开发者以新名称导出另一模块的命名空间外部对象。用于集成多个模块到一个文件

export * as ns from "mod"

关于作者

Roy
获得点赞
文章被阅读