最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • ES6复习

    正文概述 掘金(杨杨杨杨杨杨振)   2021-06-11   414

    1.let 与块级作用域

    JS中作用域有:全局作用域、函数作用域。没有块作用域的概念。ECMAScript 6(简称ES6)中新增了块级作用域。 块作用域由 { } 包括,if语句和for语句里面的{ }也属于块作用域。

    var elements = [{}, {}, {}];
    
    for (var i=0; i < elements.length; i++) {
        elements[i].onclick = function() {
            console.log(i);
        }
    }
    
    elements[1].onclick();
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    3
    3
    3
    

    1.1 通过闭包

    var elements = [{}, {}, {}];
    
    for (var i = 0; i < elements.length; i++) {
        elements[i].onclick = (function (i) {
            return function () {
                console.log(i);
            }
        })(i)
    }
    
    elements[0].onclick();
    elements[1].onclick();
    elements[2].onclick();
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    0
    1
    2
    

    1.2 使用let

    var elements = [{}, {}, {}];
    
    for (let i = 0; i < elements.length; i++) {
        elements[i].onclick = function () {
            console.log(i);
        }
    }
    
    elements[0].onclick();
    elements[1].onclick();
    elements[2].onclick();
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    0
    1
    2
    

    2. 数组的解构

    const arr = [100,200,300];
    const [a,b,c] = arr;
    console.log(a,b,c);
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    100 200 300
    
    

    2.1 只定义一个变量 需要 把其它位置空出来

    const arr = [100,200,300];
    
    const [,,c] = arr;
    
    console.log(c);
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    300
    
    

    2.2 使用...定义剩下的变量

    只能定义在最后的位置

    const arr = [100,200,300];
    
    const [a, ...rest] = arr;
    
    console.log(rest);
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    [ 200, 300 ]
    
    const arr = [100,200,300];
    
    const [...rest] = arr;
    
    console.log(rest);
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    [ 100, 200, 300 ]
    
    
    const arr = [100,200,300];
    
    const [...rest,c] = arr;
    
    console.log(rest);
    
    ////
    F:\拉钩前端\lagou\task1\task1.js:15
    const [...rest,c] = arr;
           ^^^^^^^
    

    2.3 解构的时候赋初始值

    const arr = [100, 200, 300];
    
    const [a, b, c = 123, d = 'defaultValue'] = arr;
    
    console.log(c, d);
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    300 defaultValue
    

    2.4 解构实例:解析路径

    //传统写法
    const path = '/foo/bar/baz';
    const temp = path.split('/');
    const rootdir = temp[1];
    console.log(temp);
    console.log(rootdir);
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    [ '', 'foo', 'bar', 'baz' ]
    foo
    
    
    //解构写法
    const path = '/foo/bar/baz';
    const [,rootdir] = path.split('/');
    
    console.log(rootdir);
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    foo
    

    3.对象的解构

    3.1 对象是通过key,数组是通过下标

    const obj = {name:'yangzhen' , age:24};
    
    const { name , age , sex } = obj;
    
    console.log(sex,name,age);
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    undefined yangzhen 24
    
    

    3.2 不使用别名

    const obj = {name:'yangzhen' , age:24};
    
    const name = 'jack';
    
    const { name , age , sex } = obj;
    
    console.log(sex,name,age);
    
    ////
    const { name , age , sex } = obj;
            ^
    SyntaxError: Identifier 'name' has already been declared
    
    

    3.3 使用别名 赋初始值

    const obj = {name:'yangzhen' , age:24};
    
    const name = 'jack';
    
    const { name:myname , age , sex = 18 } = obj;
    
    console.log(sex,myname,age);
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    18 yangzhen 24
    
    

    4.字符串的扩展方法

    
    const { log } = console
    
    const message = 'Error: foo is noe defined.'
    
    log (
        message.startsWith('Error'),
        message.endsWith('.'),
        message.includes('is')
    )
    
    ////
    true true true
    
    

    5.函数参数的默认值

    5.1 原始方法(对于布尔类型)

    //函数参数的默认值
    function foo(enable) {
        //原始方法(对于布尔类型)
        enable = enable === undefined ? true : false
        console.log(enable)
    }
    
    foo() //// true
    foo(false) //// false
    
    

    5.2 原始方法(对于其它类型)

    //函数参数的默认值
    function foo(enable) {
        //原始方法
        enable =  enable || 0
        console.log(enable)
    }
    
    foo()  //// 0
    foo(5) //// 5
    
    

    5.3 ES6语法

    function foo(enable = true){
        console.log(enable)
    }
    
    foo() //// true
    foo(false) //// false
    
    

    6.剩余参数

    6.1 方式一:使用arguments

    function foo(){
        console.log(arguments)
    }
    
    foo(1,2,3,4)
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    [Arguments] { '0': 1, '1': 2, '2': 3, '3': 4 }
    
    
    function foo(){
        const [a,b,c,d] = arguments
        console.log(a,b,c,d)
    }
    
    foo('a',2,3,4)
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    a 2 3 4
    
    

    6.2 方式二:使用...

    ...args放在最后 只能使用一次

    function foo(first,...args){
        
        console.log(first)
        console.log(args)
    }
    
    foo('a',2,3,4)
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    a
    [ 2, 3, 4 ]
    
    

    6.3 ···展开数组

    const arr = [1,2,3,4]
    
    console.log(...arr)
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    1 2 3 4
    
    

    7.箭头函数与this

    普通函数:this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁,一定要搞清楚这个。

    箭头函数没有prototype(原型),所以箭头函数本身没有this。箭头函数内部的this是词法作用域,由上下文确定,this指向在定义的时候继承自外层第一个普通函数的this。函数体内的this对象,就是定义时所在的对象,与使用时所在的对象无关。

    const name = 'jack'
    
    const person = {
        name: 'tom',
        sayHi: function(){
            console.log(`my name is ${this.name}`)
        }
    }
    
    person.sayHi()
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    my name is tom
    
    
    const name = 'jack'
    
    const person = {
        name: 'tom',
        sayHi: function(){
            console.log(`my name is ${name}`)
        }
    }
    
    person.sayHi()
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    my name is jack
    

    7.1 使用箭头函数

    箭头函数不会改变this的指向

    const name = 'jack' //// 这个name 并不是this.name
    
    const person = {
        name: 'tom',
        sayHi: () => {
            console.log(`my name is ${this.name}`)
        }
    }
    
    person.sayHi()
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    my name is undefined
    
    const name = 'jack'
    
    const person = {
        name: 'tom',
        sayHi: () => {
            console.log(`my name is ${name}`)
        }
    }
    console.log(this)
    console.log(this.name)
    person.sayHi()
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    {}
    undefined
    my name is jack
    

    7.2 传统方式_this的使用

    const person = {
        name: 'tom',
        sayHi: function() {
            console.log(`my name is ${this.name}`)
        },
        sayHiAsync:function(){
            setTimeout(function () {
                console.log(`my name is ${this.name}`)
            }, 1000);
        }
    }
    person.sayHi()
    person.sayHiAsync()
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    my name is tom
    my name is undefined
    
    
    const person = {
        name: 'tom',
        sayHi: function() {
            console.log(`my name is ${this.name}`)
        },
        sayHiAsync:function(){
            _this = this;
            setTimeout(function () {
                console.log(`my name is ${_this.name}`)
            }, 1000);
        }
    }
    person.sayHi()
    person.sayHiAsync()
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    my name is tom
    my name is tom
    

    7.3 setTimeout使用箭头函数 可以避免_this

    箭头函数内部的this是词法作用域,由上下文确定

    const person = {
        name: 'tom',
        sayHi: () => {
            console.log(`my name is ${this.name}`)
        },
        sayHiAsync:function(){
            setTimeout(()=> {
                console.log(`my name is ${this.name}`)
            }, 1000);
        }
    }
    person.sayHi()
    person.sayHiAsync()
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    my name is undefined
    my name is tom
    
    

    8.对象字面量增强

    const bar = '345'
    
    const obj = {
        foo: 123,
        //bar:bar
        bar,
        //method1:function(){
          //  console.log(this)
        //}
        method1(){
            console.log(this)
        },
        [Math.random()]:456 // 可以直接增加
    }
    
    //在传统方法中,对象动态的增加属性 
    obj[Math.random()] = 123
    
    console.log(obj)
    obj.method1()
    
    ////
    
    PS E:\lagou前端\demo> node .\part1\test1.js
    {
      foo: 123,
      bar: '345',
      method1: [Function: method1],
      '0.8616180359346404': 123
    }
    {
      foo: 123,
      bar: '345',
      method1: [Function: method1],
      '0.8616180359346404': 123
    }
    
    

    9.对象扩展方法

    9.1 Object.assign 将多个源对象中的属性复制到目标对象

    
    const source1 = {
        a:123,
        b:123
    }
    
    const source2 = {
        b:789,
        d:789
    }
    
    const target = {
        a:456,
        c:456
    }
    
    const result =  Object.assign(target,source1,source2)
    
    console.log(target)
    console.log(result === target)
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    { a: 123, c: 456, b: 789, d: 789 }
    true
    
    

    9.2 案例

    function func(obj){
    
        obj.name = 'func obj'
        console.log(obj)
    }
    
    const obj = {name: 'global obj'}
    
    func(obj)
    console.log(obj)
    
    ////
    { name: 'func obj' }
    { name: 'func obj' }
    
    function func(obj){
        const funObj = Object.assign({},obj)
        funObj.name = 'func obj'
        console.log(funObj)
    }
    
    const obj = {name: 'global obj'}
    
    func(obj)
    console.log(obj)
    
    ////
    { name: 'func obj' }
    { name: 'global obj' }
    

    10. Proxy代理对象

    const person = {
        name: 'yang',
        age: 18
    }
    //参数1:代理对象
    //参数2:代理的处理对象
    const personProxy = new Proxy(person,{
    
        //通过get方法去监视属性访问
        //参数1:所代理的目标对象
        //参数2:外部所访问的属性名
        get(target,property){
    
            console.log(target,property)
    
            return 100
        },
        //通过set方法去完成属性设置
        set(){
    
        }
    })
    
    console.log(personProxy.name)
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    { name: 'yang', age: 18 } name
    100
    
    
    const person = {
        name: 'yang',
        age: 18
    }
    //参数1:代理对象
    //参数2:代理的处理对象
    const personProxy = new Proxy(person,{
    
        //通过get方法去监视属性访问
        //参数1:所代理的目标对象
        //参数2:外部所访问的属性名
        get(target,property){
    
            return property in target ? target[property] : 'default'
        },
        //通过set方法去完成属性设置
        set(){
    
        }
    })
    
    console.log(personProxy.name)
    console.log(personProxy.xxxx)
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    yang
    default
    
    
    const person = {
        name: 'yang',
        age: 18
    }
    //参数1:代理对象
    //参数2:代理的处理对象
    const personProxy = new Proxy(person,{
    
        //通过get方法去监视属性访问
        //参数1:所代理的目标对象
        //参数2:外部所访问的属性名
        get(target,property){
    
            return property in target ? target[property] : 'default'
        },
        //通过set方法去完成属性设置
        //1.所代理的目标对象
        //2.要写入的属性名
        //3.要写入的值
        set(target,property,value){
            if(property === 'age') {
                if (!Number.isInteger(value)) {
                    throw new TypeError(`${value} is not an int`)
                }
            }
            target[property] = value
        }
    })
    
    personProxy.age = 30
    personProxy.sex = 'man'
    
    console.log(personProxy)
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    { name: 'yang', age: 30, sex: 'man' }
    

    11.proxy 和 Object.defineProperty()

    11.1 Object.defineProperty()只能监听对象的读写

    const person = {
        name: 'yang',
        age: 18
    }
    
    const personProxy = new Proxy(person,{
        deleteProperty(target,property){
            console.log('delete',property)
            delete target[property]
        }
    })
    
    delete personProxy.age
    
    console.log(person)
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    delete age
    { name: 'yang' }
    
    

    11.2 proxy 更好的支持数组对象的监视

    const list = []
    
    const listProxy = new Proxy(list,{
        set(target,property,value) {
            console.log('set',property,value)
            target[property] = value
            return true //表示设置成功,不写会报错
        }
    })
    
    listProxy.push(100)
    listProxy.push(200)
    console.log('list',list)
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    set 0 100
    set length 1
    set 1 200
    set length 2
    list [ 100, 200 ]
    
    

    12.Reflect 统一的对象操作API

    静态类,封装了一系列对对象的底层操作

    Reflet 成员方法就是Proxy处理对象的默认实现

    12.1 去掉Reflect

    const person = {
        name: 'yang',
        age: 18
    }
    
    const personProxy = new Proxy(person,{
        get(target,property) {
            console.log('watch logic')
           // return Reflect.get(target,property)
        }
    })
    
    console.log(personProxy.age)
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    watch logic
    undefined
    
    

    12.2 添加Reflect

    const person = {
        name: 'yang',
        age: 18
    }
    
    const personProxy = new Proxy(person,{
        get(target,property) {
            console.log('watch logic')
            return Reflect.get(target,property)
        }
    })
    
    console.log(personProxy.age)
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    watch logic
    18
    
    

    Reflect的作用:统一的提供一套用于操作对象的API

    12.3 不使用Reflect对对象的操作

    const person = {
        name: 'yang',
        age: 18
    }
    
    //判断 对象是否有 属性
    console.log('name' in person)
    //获取对象所有的Key
    console.log(Object.keys(person))
    //删除对象的属性
    console.log(delete person['age'])
    
    console.log(person)
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    true
    [ 'name', 'age' ]
    true
    { name: 'yang' }
    
    

    12.4 使用Reflect 对对象的操作

    const person = {
        name: 'yang',
        age: 18
    }
    
    //判断 对象是否有 属性
    console.log(Reflect.has(person,'name'))
    //获取对象所有的Key
    console.log(Reflect.ownKeys(person))
    //删除对象的属性
    console.log(Reflect.deleteProperty(person,'age'))
    
    console.log(person)
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    true
    [ 'name', 'age' ]
    true
    { name: 'yang' }
    
    

    13.Promise 一种更优的异步编程解决方案

    解决了传统异步编程中函数嵌套过深的问题

    14.class关键字

    14.1 传统使用prototype

    function Person (name) {
        this.name = name;
    }
    
    Person.prototype.say = function () {
        console.log(`my name is ${this.name}`)
    }
    
    const p = new Person('tom')
    
    p.say()
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    my name is tom
    
    

    14.2 使用class

    class Person {
        constructor(name) {
            this.name = name
        }
    
        say() {
            console.log(`my name is ${this.name}`)
        }
    }
    
    
    const p = new Person('tom')
    
    p.say()
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    my name is tom
    
    

    14.3 静态方法

    class Person {
        constructor(name) {
            this.name = name
        }
    
        say() {
            console.log(`my name is ${this.name}`)
        }
    
        static create(name) {
            return new Person(name)
        }
    }
    
    
    const p = Person.create('tom')
    
    p.say()
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    my name is tom
    
    

    14.4 继承

    class Person {
        constructor(name) {
            this.name = name
        }
    
        say() {
            console.log(`my name is ${this.name}`)
        }
    
        static create(name) {
            return new Person(name)
        }
    }
    
    class Student extends Person {
        constructor(name,number) {
            super(name)
            this.number = number
        }
    
        hello() {
            super.say()
            console.log(`my number is ${this.number}`)
        }
    }
    
    const s = new Student('jack',100)
    
    s.hello()
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    my name is jack
    my number is 100
    

    15.Set 数据类型

    const s = new Set()
    
    //add返回的是Set 所以可以链式调用
    s.add(1).add(2).add(3).add(4).add(4).add(5)
    
    //set 元素 没有重复 所以 自动去重
    console.log(s) //// Set { 1, 2, 3, 4, 5 }
    
    //Set的遍历
    s.forEach(i => {
        console.log(i) //// 1 2 3 4 5 
    })
    
    //Set的常用方法
    console.log(s.size) //// 5
    console.log(s.has(100)) ////false
    console.log(s.delete(3)) ////true
    console.log(s) //// Set { 1, 2, 4, 5 }
    
    

    15.1 Set 对 数组的去重处理

    Array.from() 可以将Set 转化为Array

    
    const arr = [1,2,3,1,2,1,4,1]
    
    //const result = Array.from(new Set(arr))
    
    const result = [...new Set(arr)]
    
    console.log(result)
    
    PS E:\lagou前端\demo> node .\part1\test1.js
    [ 1, 2, 3, 4 ]
    
    

    16.Map 数据结构

    16.1 普通键值对

    对象的key只能是String类型,不是String类型会被自动转化为String

    const obj = {}
    
    obj[true] = 'value'
    obj[123] = 'value'
    obj[{ a: 1 }] = 'value'
    
    console.log(Object.keys(obj))
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    [ '123', 'true', '[object Object]' ]
    
    

    16.2 Map 类型

    const m = new Map()
    const tom = { name:'tom'}
    m.set(tom,90)
    
    console.log(m)
    console.log(m.get(tom))
    
    //Map的遍历
    m.forEach((value,key)=>{
        console.log(value,key)
    })
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    Map { { name: 'tom' } => 90 }
    90
    90 { name: 'tom' }
    
    

    17.Symbol 新的数据类型

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

    const  s = Symbol()
    
    console.log(s)
    console.log(typeof s)
    console.log(Symbol() === Symbol())
    //添加描述文本
    //注意:即使添加同一描述文本 Symbol 也是不一样的
    console.log(Symbol('foo'))
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    Symbol()
    symbol
    false 
    Symbol(foo)
    

    17.2 设置对象私有成员

    const name = Symbol();
    const person = {
        [name]:'yang',
        say(){
            console.log(this[name])
        }
    }
    
    console.log(person[Symbol()])
    person.say()
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    undefined
    yang
    

    18.for of 循环

    是一种数据统一的遍历方式

    const arr = [100,200,300,400,500]
    
    for (item of arr) {
        console.log(item) ////100 200 300 400
        if(item > 300){
            break
        }
    }
    
    //不能跳出循环
    arr.forEach(item =>{
        console.log(item) ////100 200 300 400 
    })
    
    //some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。
    //some() 方法会依次执行数组的每个元素:
    //如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。
    //如果没有满足条件的元素,则返回false。
    
    //every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
    
    //every() 方法使用指定函数检测数组中的所有元素:
    
    //如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
    //如果所有元素都满足条件,则返回 true。
    const result =  arr.some((item)=>{
        return item > 300
    })
    
    console.log(result) ////true
    
    for (i in arr) {
        console.log(arr[i]) ////100 200 300 400 500
    }
    
    

    18.1 Set的 for of 遍历

    const s =  new Set(['foo','bar'])
    
    for (const item of s) {
        console.log(item)
    }
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    foo
    bar
    

    18.2 Map的 for of 遍历

    const m = new Map()
    
    m.set('foo','123')
    m.set('bar','456')
    
    for(const item of m ) {
        console.log(item)
    }
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    [ 'foo', '123' ]
    [ 'bar', '456' ]
    

    18.3 使用数组的解构得到K V

    const m = new Map()
    
    m.set('foo','123')
    m.set('bar','456')
    
    for(const [key,value] of m ) {
        console.log(key,value)
    }
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    foo 123
    bar 456
    

    19.实现可迭代接口 Iterable

    对象是不可以直接迭代的

    在对象中挂一个iterator方法,在这个方法中返回一个迭代器对象

    接口约定:内部必须要有一个用于迭代的next方法

    const obj = {
        store: ['foo','bar','baz'],
        [Symbol.iterator]: function() {
            let index = 0
            const self = this
            return {
                next: function() {
                    const result = {
                        value:self.store[index],
                        done:index >= self.store.length
                    }
                    index++
                    return result
                }
            }
        }
    }
    
    for (const item of obj) {
        console.log('循环',item)
    }
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    循环 foo
    循环 bar
    循环 baz
    

    20.迭代器模式

    20.1 实现迭代器的目的

    场景: 协同开发一个任务清单应用

    //============== 我的代码 ==============
    const todos= {
       life:['吃饭','睡觉','打豆豆'],
       learn:['语言','数学','英语'],
       
    }
    
    //============== 你的代码 ==============
    for(const item of todos.life){
       console.log(item)
    }
    
    for(const item of todos.learn){
       console.log(item)
    }
    
    
    

    如果我需要在我的todos数据列表里添加数据时,你的代码就需要作出相应的更改,对于调用来说,代码耦合度太高

    //============== 我的代码 ==============
    const todos= {
      life:['吃饭','睡觉','打豆豆'],
      learn:['语言','数学','英语'],
      work:['唱歌']
    }
    
    //============== 你的代码 ==============
    for(const item of todos.life){
      console.log(item)
    }
    
    for(const item of todos.learn){
      console.log(item)
    }
    
    for(const item of todos.work){
      console.log(item)
    }
    
    

    20.2 如何解决

    如果我的代码能够对外统一提供一个遍历的接口

    对于调用者而已,就不用去关心它内部的数据结构,也不用担心结构的改变

    我们可以自己写一个方法来实现:

    //============== 我的代码 ==============
    const todos = {
        life: ['吃饭', '睡觉', '打豆豆'],
        learn: ['语言', '数学', '英语'],
        work: ['唱歌'],
        each: function (callback) {
            const all = [].concat(this.life, this.learn, this.work)
            for (item of all) {
                callback(item)
            }
        }
    }
    
    //============== 你的代码 ==============
    todos.each(function (item) {
        console.log(item);
    })
    
    

    20.3 用迭代器的方法实现

    //============== 我的代码 ==============
    const todos = {
        life: ['吃饭', '睡觉', '打豆豆'],
        learn: ['语言', '数学', '英语'],
        work: ['唱歌'],
        [Symbol.iterator]:function() {
            //使用对象展开符 等同于 [].concat
            const all = [...this.life,...this.learn,...this.work]
            let index = 0
            return{
                next:function(){
                    return{
                        value:all[index],
                        done: index++ >= all.length //true 就迭代完成了
                    }
                }
            }
        }
    }
    
    //============== 你的代码 ==============
    for(item of todos) {
        console.log(item)
    }
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    吃饭
    睡觉
    打豆豆
    语言
    数学
    英语
    唱歌
    
    

    迭代器的核心 就是对外提供统一遍历接口,让外部不用去担心内部的数据结构是怎么样的

    这里展示的each方法只适用于这里展示的数组结构

    而ES2015种的迭代器 是从语言层面去实现的迭代器模式,所以说它适用于任何数据结构,只要实现了iterable 接口,那我们就可以实现使用for…of 遍历对象

    21.生成器函数

    解决异步编程回调嵌套过深所导致的问题

    function * foo(){
        console.log('test')
        return 100
    }
    
    const result = foo()
    console.log(result)
    console.log(result.next())
    
    ////
    Object [Generator] {}
    test
    { value: 100, done: true }
    

    21.1 惰性执行 yield

    function * foo(){
        console.log('111')
        yield 100
        console.log('222')
        yield 200
        console.log('333')
        yield 300
    }
    
    const generator = foo()
    console.log(generator)
    console.log(generator.next())
    console.log(generator.next())
    console.log(generator.next())
    console.log(generator.next())
    
    ////
    Object [Generator] {}
    111
    { value: 100, done: false }
    222
    { value: 200, done: false }
    333
    { value: 300, done: false }
    { value: undefined, done: true }
    
    

    21.2 Generator 应用

    案例一:发号器

    function * createIdMaker(){
        let id = 1
        while(true) {
            yield id++
        }
    }
    
    const idMaker = createIdMaker()
    console.log(idMaker.next().value)
    console.log(idMaker.next().value)
    console.log(idMaker.next().value)
    console.log(idMaker.next().value)
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    1
    2
    3
    4
    
    

    案例二:使用Generator 函数实现Iterator方法

    const todos = {
        life: ['吃饭', '睡觉', '打豆豆'],
        learn: ['语言', '数学', '英语'],
        work: ['唱歌'],
        [Symbol.iterator]: function* () {
            const all = [...this.life, ...this.learn, ...this.work]
            for (item of all) {
                yield item
            }
        }
    }
    
    for (const item of todos) {
        console.log(item)
    }
    
    ////
    PS E:\lagou前端\demo> node .\part1\test1.js
    吃饭
    睡觉
    打豆豆
    语言
    数学
    英语
    唱歌
    
    

    22.ES2016

    22.1 Array.prototype.includes

    我们先看看indexOf方法

    const arr = ['foo',1,NaN,false]
    
    console.log(arr.indexOf('foo'))
    console.log(arr.indexOf(1))
    console.log(arr.indexOf(NaN))
    console.log(arr.indexOf(false))
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    0
    1
    -1
    3
    

    indexOf 无法检查出NaN

    注意点:NaN是唯一一个和自身不相等的值:NaN === NaN // false

    22.2 includes 可以检查出NaN 返回布尔值

    const arr = ['foo',1,NaN,false]
    
    console.log(arr.includes('foo'))
    console.log(arr.includes(1))
    console.log(arr.includes(NaN))
    console.log(arr.includes(false))
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    true
    true
    true
    true
    
    

    22.3 指数运算符

    console.log(Math.pow(2,10))
    console.log(2 ** 10)
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    1024
    1024
    

    23.ES2017

    23.1 Object.values

    const obj = {
        foo: 'value1',
        bar: 'balue2'
    }
    
    console.log(Object.values(obj))
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    [ 'value1', 'balue2' ]
    

    23.2 Object.entries

    数组形式返回键值对

    const obj = {
        foo: 'value1',
        bar: 'balue2'
    }
    
    console.log(Object.entries(obj))
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    [ [ 'foo', 'value1' ], [ 'bar', 'balue2' ] ]
    
    

    因此可以使用for of

    const obj = {
        foo: 'value1',
        bar: 'balue2'
    }
    
    for (const [key, value] of Object.entries(obj)) {
        console.log(key, value)
    }
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    foo value1
    bar balue2
    
    

    使用entries 转化 Map对象

    const obj = {
        foo: 'value1',
        bar: 'balue2'
    }
    
    console.log(new Map(Object.entries(obj)))
    
    ////
    PS F:\拉钩前端\lagou> node .\task1\task1.js
    Map { 'foo' => 'value1', 'bar' => 'balue2' }
    
    

    起源地下载网 » ES6复习

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元