ES6掌握不太熟的属性

145 阅读5分钟

ES6在前端中泛指ES2015之后javascript所发布的新的规范。

Proxy

监视到更多object.defineProperty监视不到的行为

get,set,has,deleteProperty,getPrototypeOf,setPrototypeOf,isExtensible,preventExtensions,getOwnPropertyDescriptor,defineProperty,apply,construct

const person = {
  age: 200,
  name: "zoe",
};
const personProxy = new Proxy(person, {
  deleteProperty(target,property){
      console.log('delete',property);	// delete age
      delete target[property]
  }
});
delete personProxy.age 
console.log(person);// { name: 'zoe' }

更好的支持数组对象的监视,

vue2 重写数组的操作方法

const list = []
const personProxy = new Proxy(list, {
  get(target, property) {
    return property in target ? target[property] : undefined;
  },
  set(target, property, value) {
    target[property] = value;
    return
  },
});

Proxy 是以非侵入的方式监管了对象的读写

不需要对对象本身做任何操作就可以监视到内部成员的读写

Reflect

静态类,不能通过new 创建
内部封装了一系列对对象的底层操作,Reflect成员方法就是Proxy处理对象的默认实现 统一了对象的操作方式,提供了一套统一的用于操作对象的API

const proxy = new Proxy(obj,{
    get(target,property){
        return Reflect.get(target,property) // 当没有定义自定义相关方法的实现时,自动使用Reflect的同名方法
    }
})

Symbol

Symbol的值都是独一无二的,可以避免同一个对象属性名重复的问题
Symbol('bar') === Symbol('bar) // false

es2015 对象的key 可以是string和Symbol,但是一般我们使用的Object.keys() for in JSON.stringify都不能获取到以对象中以Symbol为属性名的键值对,只能通过Object.getOwnPropertySymbols()来获取

最主要的作用就是为对象添加独一无二的属性名

顺带提一句js的原始数据类型7种 number string boolean undefined null Symbol bigInt加上object一共是8种数据类型

for...of

可以被for...of遍历的数据类型都必须要实现Iterator可迭代接口,内部必需要挂载一个Iterator方法,这个方法需要返回一个带有next()方法的对象,不断调用next()方法就可以实现对内部数据的遍历

Iterator可迭代接口

const set = new Set(['foo','bar','baz'])
const iterator = set[Symbol.iterator]()
console.log(iterator.next())    // { value: 'foo', done: false }
console.log(iterator.next())    // { value: 'bar', done: false }
console.log(iterator.next())    // { value: 'baz', done: false }
console.log(iterator.next())    // { value: undefined, done: true }
实现可迭代接口
const obj = {
  store: ["foo", "bar", "baz"],
  // [Symbol.iterator] 由于是Symbol提供的一个常量,所以要用计算属性名的方式定义到对象中
  // 实现了可迭代接口   Iterable
  [Symbol.iterator]: function () {
    let index = 0;
    const self = this;
    return {
      // 实现了迭代器接口  Iterator
      next: function () {
        const result = {
          // 迭代结果接口  IterationResult
          value: self.store[index],
          done: index >= self.store.length,
        };
        index++;
        return result;
      },
    };
  },
};
迭代器设计模式

核心:对外提供统一遍历接口,让外部不用关心数据内部结构是怎样的

生成器Generator

也是避免异步编程中回调函数嵌套过深的问题,提供更好的异步编程解决方案

生成器函数会自动返回一个生成器对象Object [Generator] {},调用这个对象的next方法,才会让这个函数的函数体开始执行,执行过程中,一旦遇到yield关键词,函数的执行就会暂停下来,yield后面的值,将会作为next方法的结果返回,如果继续调用next,函数会从暂停的位置继续开始执行,一直到函数完全结束,这个时候next方法返回的值中的done属性的值就会变成true,这就是生成器函数的执行过程,特点就是惰性执行

function * foo(){
    console.log('zoe');
    return 100
}

const result = foo()
console.log(result);// Object [Generator] {} 内部有next方法,可在浏览器控制台中查看
console.log(result.next()); // zoe
                            // { value: 100, done: true }
function* foo() {
  console.log("1111");

  yield 100;

  console.log("2222");
  yield 200;

  console.log("3333");
  yield 300;
}

const generator = foo();
console.log(generator.next());
// 1111
// { value: 100, done: false }
console.log(generator.next());
// 2222
// { value: 200, done: false }
console.log(generator.next());
// 3333
// { value: 300, done: false }
console.log(generator.next());
// { value: undefined, done: true }
生成器应用

使用Generator函数实现iterator方法

const obj = {
  store: ["foo", "bar", "baz"],
  // [Symbol.iterator] 由于是Symbol提供的一个常量,所以要用计算属性名的方式定义到对象中
  // 实现了可迭代接口   Iterable
  [Symbol.iterator]: function* () {
    for (const item of this.store) {
      yield item;
    }
  },
};

for (const item of obj) {
  console.log(item);
  // foo
  // bar
  // baz
}

ES Module 语言层面的模块化规范

CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
CommonJS 模块是运行时加载,ES6 模块是编译时输出接口
CommonJS 模块是单个值导出的,ES6 模块是可以导出多个
CommonJS 可以写在判断里面,ES6 只能写在顶层
CommonJS 模块this是当前模块,ES6 模块this是undefined

commonJs是运行时加载,esModule是编译输出的接口的差异是因为CommonJS加载的是一个对象(module.exports属性),该对象只有在脚本运行完才会生成,而ES6 模块不是对象,他的对外接口只是一种静态的定义,在代码解析阶段就会生成,js 引擎在对脚本静态分析的时候,遇到模块加载命令import,会生成一个只读引用,等到脚本真正执行的时候,才会根据这个引用去取值

ES2016新特性

Array.prototype.includes()
指数运算符
Math.pow(2,10) 等价于 2 ** 10

ES2017新特性

Object.values()

const obj ={
    foo:'value1',
    bar:'value2'
}
console.log(Object.values(obj)); // [ 'value1', 'value2' ]

Object.entries()

console.log(Object.entries(obj));   // [ [ 'foo', 'value1' ], [ 'bar', 'value2' ] ]

Object.getOwnPropertyDescriptor()

获取对象中属性完整描述信息  主要是配合ES5的getset使用
const descriptors = Object.getOwnPropertyDescriptor(obj) 
Object.defineProperties({},descriptors)

String.prototype.padStart() String.prototype.padEnd()
作用就是补齐位置,具体可以百度

在函数参数中,添加尾逗号
async/await