ES6学习笔记

169 阅读4分钟

个人感悟

    这次拉勾课里面Es6的课程大部分都在平时的编码里面用过,也比较熟悉所以这些都先不记录暂时,记一下之前了解不多的知识点,先罗列下要记载的知识点: 1、带标签的模版字符串
2、字符串的扩展方法
3、Object.is
4、Proxy
5、Reflect
6、Set
7、Map
8、for...of.../迭代器
9、ES2017中Object。entries

    这一部分学习我觉得也是用代码比较好、因为编程毕竟是工科,能动手就不逼逼,一开始写文想着冲奖金去,后面思考了一下,这样的笔记写的太全有太多干扰

正文

1、带标签的模版字符串和字符串扩展方法

const name = 'Tracy';
const answer = true;
function comment(strings, first, second) {
//strings = ['is ', ' a man ? ', ' !']
//first = 'Tracy''
//second = answer
    return strings[0] + first.st +  strings[1] + second ? 'yes' : 'no' + string[2];
};
//speak = is Tracy a monster ? yes !;
const speak = comment`is ${name} a monster ? ${answer} !`;

2、Object.is判断两个数是否相等,用处不大,还是更多地使用===

Object.is(NaN, NaN) //true
Object.is(+0, -0) //false

3、Proxy和Reflect
个人觉得最有用的,为后面Vue3打基础

const person2 = {
  name: 'yellow sir',
  age: 99
}

const personProxy = new Proxy(person2, {
  //target目标对象,property读取属性
  get (target, property) {
    console.log('get', target, property)
    return Reflect.has(target, property) ? Reflect.get(target, property) : 'default'
  },
    //target目标对象,property读取属性,value赋值
  set (target, property, value) {
    console.log('set', target, property, value)
    Reflect.set(target, property, value);
  },
  deleteProperty (target, property) {
    console.log('delete', target, property)
    Reflect.deleteProperty(target, property);
  }
})

personProxy.name = 'jack1'
console.log(personProxy.name)
delete personProxy.age;
console.log(personProxy)

//最终输出:
//set { name: 'yellow sir', age: 99 } name jack1
//get { name: 'jack1', age: 99 } name
//jack1
//delete { name: 'jack1', age: 99 } age
//{ name: 'jack1' }

Proxy和Object.defineProperty的不同:
1、Proxy功能更强大,除了读写外、Reflect上的方法都可以拦截处理
2、Proxy可以监听数组而Object.defineProperty不行,这个时候只能重写数组的方法 3、Proxy以非侵入式监控对象的读写,不需要对目标做其他额外的操作就可以监控目标的读写

下面Reflct的API摘录自MDN

Reflect.apply(target, thisArgument, argumentsList)
对一个函数进行调用操作,同时可以传入一个数组作为调用参数。和Function.prototype.apply() 功能类似。
Reflect.construct(target, argumentsList[, newTarget])
对构造函数进行 new 操作,相当于执行 new target(...args)。
Reflect.defineProperty(target, propertyKey, attributes)
和 Object.defineProperty() 类似。如果设置成功就会返回 true
Reflect.deleteProperty(target, propertyKey)
作为函数的delete操作符,相当于执行 delete target[name]。
Reflect.get(target, propertyKey[, receiver])
获取对象身上某个属性的值,类似于 target[name]。
Reflect.getOwnPropertyDescriptor(target, propertyKey)
类似于 Object.getOwnPropertyDescriptor()。如果对象中存在该属性,则返回对应的属性描述符, 否则返回 undefined.
Reflect.getPrototypeOf(target)
类似于 Object.getPrototypeOf()。
Reflect.has(target, propertyKey)
判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同。
Reflect.isExtensible(target)
类似于 Object.isExtensible().
Reflect.ownKeys(target)
返回一个包含所有自身属性(不包含继承属性)的数组。(类似于 Object.keys(), 但不会受enumerable影响).
Reflect.preventExtensions(target)
类似于 Object.preventExtensions()。返回一个Boolean。
Reflect.set(target, propertyKey, value[, receiver])
将值分配给属性的函数。返回一个Boolean,如果更新成功,则返回true。
Reflect.setPrototypeOf(target, prototype)
设置对象原型的函数. 返回一个 Boolean, 如果更新成功,则返回true。

4、Set和Map
本质都是集合,可以用for...of遍历,Map和普通对象的不同之处是键值保留原有数据类型而普通对象键值会变成字符串(Symbol除外)

5、Symbol
Symbol目前最大的用处就是为对象申明唯一的属性,下面通过手写bind、call、apply来看一下.Symbol作为属性名时,不会被for...in...,Objeckt.keys(),JSON.stringfy()读取所以适合做私有属性

Symbol('foo') === Symbol('foo') //false
Symbol.for('foo') === Symbol.for('foo') //true
Symbol.for(true) === Symbol.for('true') //true
//存在一些Symbol常量Symbol.iterator、Symbol.toPrimitive、Symbol.toStringTag

Function.prototype.call = (context, ...args) => {
    context = context || window;
    const symbolFn = Symbol('fn');
    context[symbolFn] = this;
    const result =  context[symbolFn](...args);
    delete context[symbolFn];
    return result;
}

Function.prototype.apply = (context, args) => {
  context = context || window;
  const symbloFn = Symbol('fn');
  context[symbloFn] = this;
  const result = context[symbloFn](...args);
  delete context[symbloFn];
  return result;
}

Function.prototype.bind = (context, args) => {
  context = context || window;
  const symbloFn = Symbol('fn');
  context[symbloFn] = this;
  return function (..._args) {
    const result = context[symbloFn](...args, ..._args);
    delete context[symbloFn];
    return result
  }
}

const obj = {
  [Symbol()]: 'symbol value',
  foo: 'normal value'
}
// for (var key in obj) {
//   console.log(key)
// }
// console.log(Object.keys(obj))
// console.log(JSON.stringify(obj))

console.log(Object.getOwnPropertySymbols(obj))

6、for..of...可以循环遍历任意实现Iterable接口的类型像数组、Map、Set。普通对象只要也实现了这个属性也可以使用for...of...遍历

const obj = {
  age: 18,
  name: 'tom',
  own: ['car', 'house'],
  [Symbol.iterator]: function * () {
    const all = [this.age, this.name, this.own];
    for (item of all) {
      yield item;
    }
  }
}

//obj可以通过for..of...循环,但我个人觉得实现成本太高,不如直接for..in...

7.Object.entries

const obj = {
  age: 18,
  name: 'tom'
}
Object.entries(obj) //[[age, 18], [name, 'tom']]