ES干货集锦

ES6

babel

命令行的快捷键

新的变量声明关键字 let 与 const

JS的第七种数据类型 Symbol

解构赋值

字符串的扩展方法及模板字符串

// es5
{
    const str1 = 'a'
    const str2 = '\u20bb7'
    console.log(str2) //乱码, 超出了es5可以处理的范围
}
// es6
{
    const str3 = '\u{20bb7}'
    console.log('str3', str3)
}

// for of  ---适用范围更广的for循环
{
    const str3 = '\u{20bb7}'
    // 传统的for循环
    for(let i = 0; i < str3.length; i++) {
        console.log('for', str3[i]) //乱码
    }
    for(let word of str3) {
        console.log('for-of', word)
    }
}

// 判断字符串中是否包含指定字符串的几个方法
{
    let str = '123Nick'
    // 判断字符串中是否包含指定字符串
    console.log('includes', str.includes('Nick')) // true
    // 判断字符串是否以指定字符串开头
    console.log('startsWith', str.startsWith('Nick')) // false
    // 判断字符串第n个字符串开始是否包含指定字符串
    console.log('startsWith', str.startsWith('Nick', 3)) // true
    // 判断字符串自开头开始往后多少位前是否含有指定字符串
    console.log('endsWith', str.endsWith('Nick', 7)) // true
}

// 将字符串重复指定次数
{
    let str = 'Nick123'
    str = str.repeat(3)
    console.log('repeat', str)
}

// 字符串补全
{
    let str = 'Apple'
    // 头部补全----第一个参数是补全后的字符串长度,第二个参数是用来补全的字符串
    str = str.padStart(8, 'asdad')
    console.log('padStart', str) //asdApple
    // 尾部补全函数是: padEnd(), 用法同上
}

// 模板字符串
{
    const name = 'nick'
    const age = 18
    const str = `我叫${name},我今年${age}岁.`
    console.log(str)
}

数组的扩展方法及扩展运算符的使用

对象的新特性及新增方法

Map与WeakMap结构的特点

Set与WeakSet

Map、Set、Array、Object间的区别

代理Proxy和反射Reflect

使用Proxy和Reflect实现简单的双向数据绑定

  1. index.html

    <body>
        <script src="./polyfill.js"></script>
        <!-- <script src="dist/chapter3-1.js"></script> -->
        <h1>使用Proxy和Reflect实现双向数据绑定</h1>
        <input type="text" id="input">
        <h2>您输入的是: <i id="txt"></i></h2>
       
        <!-- script标签要放在上面内容之下 -->
        <script src="src/4-8-使用Proxy和Reflect实现双向数据绑定.js"></script>
    </body>
    
  2. 获取dom对象

    const inputObj = document.getElementById('input')
    const txtObj = document.getElementById('txt')
    
  3. 设置代理对象

    const obj = {}
    
  4. 配置代理选项

    const handler = {
            get: function(target, key) {
                return Reflect.get(target, key)
            },
       
            set: function(target, key, value) {
                if(key === 'text') {
                    // Start 实现 i 标签内容同步到input
                    inputObj.value = inputObj.value === value ? inputObj.value : value
                    // END  实现 i 标签内容同步到input
                    txtObj.innerHTML = value
                }
                return Reflect.set(target, key, value)
            }
        }
    
  5. 添加事件

    let objProxy = new Proxy(obj, handler)
       
        // 给input添加键盘键入事件
        inputObj.addEventListener('keyup', function(e) {
            objProxy.text = e.target.value
            console.log(objProxy)
        })
    
  6. 完整代码:

    {
        // 获取dom元素
        const inputObj = document.getElementById('input')
        const txtObj = document.getElementById('txt')
       
        // 初始化代理对象
        const obj = {}
       
        // 配置代理选项
        const handler = {
            get: function(target, key) {
                return Reflect.get(target, key)
            },
       
            set: function(target, key, value) {
                if(key === 'text') {
                    // Start 实现 i 标签内容同步到input
                    inputObj.value = inputObj.value === value ? inputObj.value : value
                    // END  实现 i 标签内容同步到input
                    txtObj.innerHTML = value
                }
                return Reflect.set(target, key, value)
            }
        }
       
        let objProxy = new Proxy(obj, handler)
       
        // 给input添加键盘键入事件
        inputObj.addEventListener('keyup', function(e) {
            objProxy.text = e.target.value
            console.log(objProxy)
        })
       
        // 现在当你在输入框中输入内容时会自动同步到 i 标签
        // 但是 i 标签内容的修改还无法同步到input
            // 修改 i 标签内容,发现不会同步到input
        objProxy.text = '1234'
       
        // 要真正实现双向数据绑定还需要在拦截set中对输入框进行处理(见set里的代码注释)
    }
    

函数的扩展

箭头函数

ES6中类的概念

JS中的模块化开发(import 和 export)

异步编程及JS的异步实现

Promise

Iterator和for…of

更直观的异步编程写法__Generator

{
    // 本质仍然是Iterator
    const say = function* () {
        yield 'a'
        yield 'b'
        yield 'c'
    }

    const fn = say();
    console.log(fn.next()) // {value: 'a', done: false}
    // next始终是用来启动yield生成器的, 所以, next始终要比yield多一个
    // 最后一个的done为true
}

{
    // 更简洁地为对象定义迭代器
    let obj = {
        a: 1,
        b: 2,
        c: 3
    }
    obj[Symbol.iterator] = function* () {
        for(const key of Object.keys(obj)) {
            yield obj[key]
        }
    }

    for(const value of obj) {
        console.log(value)
    }
    // 1 2 3
}

{
    // 可用来定义状态机
    // 状态机: 任何时候都只有一定数量种状态
    const state = function* () {
        while(1) {
            yield 'success'
            yield 'fail'
            yield 'pending'
        }
    }
    const stateData = state()
    console.log(stateData.next()) // {value: 'success', done: false}
    console.log(stateData.next()) // {value: 'fail', done: false}
    console.log(stateData.next()) // {value: 'pending', done: false}
    console.log(stateData.next()) // {value: 'success', done: false}
    console.log(stateData.next()) // {value: 'fail', done: false}
}

{
    // 可用来定义长轮询
    // 以下代码会一直查询用户付款状态, 直到付款code为0
    function fn1() {
        return new Promise(resolve => {
            // 模拟查询操作
            setTimeout( () => {
                console.log('查询中')
                resolve({code: 0})
            },1000)
        })
    }
    const getStatus = function* () {
        yield fn1()
    }
    function autoGetStatus() {
        const gen = getStatus()
        const status = gen.next()
        // 还记得吗? iterator的next()返回中有value和done两个值, 这里的status.value就是fn1返回的Promise
        status.value.then(res => {
            if(res.code === 0) {
                console.log('用户付款成功')
            } else {
                console.log('暂未付款')
                // 继续查询
                setTimeout( () => autoGetStatus(), 500)
            }
        })
    }
    autoGetStatus()
}

{
    //todo 如何用同步的写法来写异步编程
        // generator本身不是用来异步编程, 但大神们把他的特性用在了异步编程里, nice!
    const ajax = function* () {
        console.log('start')
        yield function(cb) {
            setTimeout(() => {
                console.log('异步任务结束')
                cb && cb()
            }, 1000)
        }
        console.log('end')
    }
    // const runAjax = ajax()
    // console.log(runAjax.next())
    // console.log(runAjax.next())
    const runAjax = ajax() // 生成一个generator实例
    const first = runAjax.next() // 将generator状态(next)保存起来 ---当前输出 'start'
    first.value(() => runAjax.next()) // 为next.value传入回调函数, 这里的回调函数就是通过generator执行next
    //输出:  start   异步任务结束   end
}

更优雅的异步编程__async

总结