0
点赞
收藏
分享

微信扫一扫

学习笔记-ES2015--22-03-05(Symbol,for...of...,Iterator,generator,getter setter,ES2016,ES2017)

DYBOY 2022-03-11 阅读 17

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)

举报

相关推荐

0 条评论