1.Symbol
symbol是一种新基本类型;最主要的作用是定义独一无二的属性名,也可以借助这种特性,保护私有变量,因为外界无法生成一摸一样的symbol 所以访问不到 ;
如果想要复用这个Symbol 可以使用静态方法Symbol.for(value: string);全局会有注册表记录这个字符串与symbol的对应关系 所以如果传入的值非字符串 会被转化为字符串;
Symbol属性无法被for.in和Object.keys() 等获取到,同样在json序列化时也会忽略symbol属性值; 但可以通过Object.getOwnPropertySymbols() 获取
obj = {name: 'zs', age:22, [Symbol()]:2};
console.log(Reflect.has(obj, 'name')); // true
console.log(Reflect.deleteProperty(obj, 'name')); // true
console.log(Reflect.ownKeys(obj)); // [ 'age', Symbol() ]
console.log(Object.getOwnPropertySymbols(obj)); // [ Symbol() ]
2.for...of...
for of 是一种遍历所有数据结构的统一方式 需要数据实现可迭代接口 iterable接口
for of 可以使用break终止循环 for of可以遍历所有可迭代的对象 甚至伪数组 Set Map
遍历map获取到的是一个数组, 数组0为key 1为值 for ( const [key, value] of map)
arr.forEach() // 不可以终止循环
arr.some(); return true 终止
arr.every(); return false 终止
const arr = [1,2,3,4,2,2,44];
for (const item of arr) {
console.log(item);
if (item >= 4) break;
}
// 可以通过break跳出循环
为什么用const定义for of 而普通for使用const会报错?
因为for in 和for of 会为每一次循环创建一个单独的块级作用域 使用const来确保值不会被修改而普通for只会创建一个块级作用域;
3.iterator
在使用for of对数据结构进行遍历时 需要实现Iterable接口
通过打印数组 set map等可迭代数据结构发现,他们原型对象中(__proto__)都有:
Symbol(Symbol.iterator): ƒ values()
arguments: (...)
caller: (...)
length: 0
name: "values"
__proto__: ƒ ()
[[Scopes]]: Scopes[0]
调用这个方法 看到有个next方法:
Array Iterator {}
__proto__: Array Iterator
next: ƒ next()
arguments: (...)
caller: (...)
length: 0
name: "next"
__proto__: ƒ ()
[[Scopes]]: Scopes[0]
Symbol(Symbol.toStringTag): "Array Iterator"
__proto__: Object
通过set结构来查看 获取并执行next:
const set = new Set();
set.add("22").add("33").add("wa");
const iterator = set[Symbol.iterator]();
console.log(iterator.next()); // { value: '22', done: false }
console.log(iterator.next()); // { value: '33', done: false }
console.log(iterator.next()); // { value: 'wa', done: false }
console.log(iterator.next()); // { value: undefined, done: true }
console.log(iterator.next()); // { value: undefined, done: true }
手动模拟这个迭代器:
const obj = {
arr: ['qqq','www','eee'],
[Symbol.iterator]: function() {
let index = 0;
const self = this;
console.log(this);
/**
* {arr: [ 'qqq', 'www', 'eee' ],
[Symbol(Symbol.iterator)]: [Function: [Symbol.iterator]]}
*/
return {
next() {
const result = {
value: self.arr[index],
done: index >= self.arr.length,
}
index ++;
return result;
}
}
}
}
for (const item of obj) {
console.log(item);
// qqq
// www
// eee
}
4.generator生成器
ES2015出现 主要为了解决异步嵌套的问题;但是有弊端:需要额外定义一个执行器方法调用next()等方法 专门执行生成器对象;
function * a() {
let index = 0;
console.log(index); // 0
const obj1 = yield index++;
console.log(obj1); // undefined
const obj2 = yield index++;
console.log(obj2); // 1
const obj3 = yield index++;
console.log(obj3);
const obj4 = yield index++;
console.log(obj4);
return 'return 1';
}
const g = a();
console.log(g); // Object [Generator] {}
let value = g.next();
console.log(value,333); // { value: 0, done: false }
value = g.next();
console.log(value,334); // { value: 1, done: false }
value = g.next(value.value);
console.log(value); // { value: 2, done: false }
使用生成器可以更方便的定义可迭代属性:
// 可以通过生成器来实现迭代器
const obj = {
arr: ['qqq','www','eee'],
[Symbol.iterator]: function * () {
const all = [...this.arr,]
for (const item of all) { // 这里使用for of 是因为数组默认实现了迭代器 也可以使用其他方法迭代
yield item;
}
}
}
for (const item of obj) {
console.log(item);
// qqq
// www
// eee
}
// 将迭代器返回一个生成器函数 在外部通过for of访问时 for of 会调用迭代器的next方法这样 就可以循环遍历对象了
5.getter setter
getter ES2015 get property () {return ...} 不可以带参数
set prop(val) { . . . } 一个参数
ES2015后可以使用 get [express]() {} 定义计算属性名的getter和setter
创建出来的属性是伪属性 为其赋值并不会影响他
可以使用delete删除
可以使用defineProperty对现有对象定义;
延时计算 需要时才计算 定义时可以借助缓存 优化性能;
当使用 get 关键字时,它和Object.defineProperty() 有类似的效果,在classes中使用时,二者有细微的差别。
当使用 get 关键字时,属性将被定义在实例的原型上,当使用Object.defineProperty()时,属性将被定义在实例自身上。
Object.assign 不能复制getter和setter 复制过去的是固定值(见Object.assign 22.03.04)
如果想要复制getter和setter,可以使用getOwnPropertyDescriptor获取到指定属性的描述符信息,然后通过defineProperty添加描述符
class Example {
get hello() {
return 'world';
}
}
const obj3 = new Example();
console.log(obj3.hello);
// "world"
console.log(Object.getOwnPropertyDescriptor(obj3, 'hello'));
// undefined
console.log(
Object.getOwnPropertyDescriptor(
Object.getPrototypeOf(obj3), 'hello'
)
);
// { configurable: true, enumerable: false, get: function get hello() { return 'world'; }, set: undefined }
6.ES2016新特性
arr.includes()判断数组是否存在指定value,返回boolean 判断两个NaN相等
arr.indexOf()返回索引 找不到则返回-1 判断两个NaN不等
指数运算符** 2**10 === 1024
7.ES2017新特性
Object.values(obj)返回对象所有值的Array
Object.entries(obj)返回对象所有键值对的Array 键值也是Array
可以使用entries搭配for of实现遍历 而不用实现iterable接口
for (const [key, value] of Object.entries(obj)) {
console.log(key, value);
}
Object.getOwnPropertyDescriptors()
方法用来获取一个对象的所有自身属性的描述符
Object.getOwnPropertyDescriptor(obj1,'all')方法返回该对象该属性的描述符;
Async/Await 相比生成器更加简洁 同步的书写方式更加易读 实际上是promise语法糖;在return一个普通值是 会将其包装为Promise 类似于 Promise.resolve()静态方法;(Promise源码学习笔记needtodo)