ES6

67 阅读8分钟

1.let、const

let
    1let声明的变量只在代码块内有效(块级作用域),for循环适合用
    2let不允许在相同作用域内,重复声明同一个变量。
    3)不存在变量提升
    4)暂时性死区(在代码块内,使用let命令声明变量之前,该变量都是不可用的) 
const
    1)变量指向的那个内存地址所保存的数据不得改动,即常量值不可变,对象的值可变
es6声明属性六种方法
    var
    function
    let
    const
    import
    class
顶层对象
    顶层对象,在浏览器环境指的是window对象,在 Node 指的是global对象
        es5 顶层对象的属性与全局变量是等价的
        es6中let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性

// 2.变量的解构赋值
/*
    数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
*/
// 3.字符串的扩展
/*
    模板字符串
 */
// 4.字符串的新增方法
/*
    includes(), startsWith(), endsWith('world', 6)   返回布尔值
    repeat()  返回一个新字符串,表示将原字符串重复n次
    padStart(5, 'ab')用于头部补全,padEnd()用于尾部补全
    trim()一致,trimStart()消除字符串头部的空格,trimEnd()消除尾部的空格
    'aabbcc'.replaceAll('b', '_')
 */
// 5.数值的扩展
/*
    Number.isFinite()和Number.isNaN()
    Number.parseInt(), Number.parseFloat()
    Number.isInteger() 
    Math.trunc()    去除一个数的小数部分,返回整数部分
 */
// 6.函数的扩展
/*
    函数的参数指定默认值
    rest 参数之后不能再有其他参数(即只能是最后一个参数)
        function add(...values) {}    values是个数组
    箭头函数
        箭头函数没有自己的this对象
            对于普通函数来说,内部的this指向函数运行时所在的对象,但是这一点对箭头函数不成立。
            它没有自己的this对象,内部的this就是定义时上层作用域中的this。
            也就是说,箭头函数内部的this指向是固定的,相比之下,普通函数的this指向是可变的。
        不使用场合
            定义对象的方法,对象不构成单独的作用域
            需要动态this的时候
 */ 
// 6.数组的扩展
/*
    扩展运算符(...)
        rest参数的逆运算,将一个数组变为参数序列
        扩展运算符的应用
            复制数组   a2=[...a1]
            合并数组   [...a1,...a2]
            Map 和 Set 结构,Generator 函数
                扩展运算符内部调用的是数据结构的 Iterator 接口,因此只要具有 Iterator 接口的对象,都可以使用扩展运算符
    Array.from()
        Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)
*/           
// 7.对象的方法
/*
    Object.is()
        它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。
    Object.assign(target, source1, source2)
        用于对象的合并
        浅拷贝,而不是深拷贝
        可枚举属性 Object.defineProperty  enumerable
    Object.keys()
        返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名
    Object.values()
        返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值
    Object.entries()
        返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组
 */
// 8.Promise
/*
    异步编程解决方案
    所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果
    是个构造函数,new一个实例
        let p = new Promise(function(resolve,reject){
            // 同步调用
            console.log('111)
            // 保存异步结果
            resolve(value)   // 异步操作成功时调用,保留异步成功的结果value
            reject(error)    // 在异步操作失败时调用,保留异步失败的结果error
        })
        let p1 = p.then(function success(value){},function error(error){})
    有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)
        状态发生改变会触发then()里的响应函数处理后续步骤
        一旦状态改变,就不会再变,任何时候都可以得到这个结果
            从pending变为fulfilled 或 从pending变为rejected
    Promise.prototype.then()
        then方法返回的是一个新的Promise实例
    Promise.prototype.catch()
        Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。
    Promise.prototype.finally() 
        用于指定不管 Promise 对象最后状态如何,都会执行的操作
        promise
        .then(result => {···})
        .catch(error => {···})
        .finally(() => {···});
    Promise.all([p1, p2, p3])  要全成功才成功
        Promise.all中的执行的顺序其实应该是并行的
        将多个 Promise 实例,包装成一个新的 Promise 实例
            const p = Promise.all([p1, p2, p3]);
            只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数
            只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数
    Promise.race()
        将多个 Promise 实例,包装成一个新的 Promise 实例
        只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数(返回值为最快完成的那个promise结果)
    Promise.allSettled()
        用来确定一组异步操作是否都结束了(不管成功或失败)
    Promise.any()
        等到所有参数 Promise 变成rejected状态才会结束。
        有一个变成fulfilled,Promise.any()返回的 Promise 对象就变成fulfilled。
    Promise.resolve()、Promise.reject()
        将现有对象转为 Promise 对象
*/
// 8.Generator 函数
/*
    异步编程解决方案
    一个状态机,封装了多个内部状态
    Generator 函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield表达式就是暂停标志。
        function* helloWorldGenerator() {
            yield 'hello';
            yield 'world';
            return 'ending';
        }
        let hw = helloWorldGenerator()  // 遍历器对象
        hw.next()
    yield表达式与return语句既有相似之处,也有区别。
        相似之处在于,都能返回紧跟在语句后面的那个表达式的值
        区别在于每次遇到yield,函数暂停执行,下一次再从该位置继续向后执行,而return语句不具备位置记忆的功能(return只能执行一次)
    ES6 诞生以前,异步编程的方法,大概有下面四种。
        回调函数
        事件监听
        发布/订阅
        Promise 对象 - 只是回调函数的改进,使用then方法以后,异步任务的两段执行看得更清楚了      
*/
// 8.async 函数  await
/*
    异步编程解决方案
    async 函数就是 Generator 函数的语法糖
        写法上 async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已
    await 也是状态机,只有await后的代码执行完成后才能向后执行,
        await后是个promise对象,返回该对象的结果
    错误捕获
        async函数返回一个 Promise 对象
        必须等到内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。
        任何一个await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行。
*/
// 9.Class
/*
    ES6 的class可以看作只是一个语法糖,ES5 构造函数 + prototype
        class Person{
            // 构造方法
            constructor(a,b,c){
                // this关键字则代表实例对象
                this.a = a
                this.b = b
                this.c = c
            }
            // 类的所有方法都定义在类的prototype属性上面
            print(){
                console.log("print")
            }
        }
        let one = new Person('a','b','c')
    get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
    this它默认指向类的实例,this一直指向类的实例的方法
        constructor方法中绑定this
            this.fn = this.fn.bind(this);
        箭头函数
            this.fn = ()=>{}
    static(静态方法)
        在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
    继承
        class A extends B{
            constructor(a,b,c,d){
                // 调用父类的constructor(x, y)
                // super在这里表示父类的构造函数,用来新建一个父类的实例对象。
                super(a,b)
                this.c = c
                this.b = b
            }
        }
        子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,添加子类自己的实例属性和方法。如果不调用super()方法,子类就得不到自己的this对象。
        ES5 的继承机制,是先创造一个独立的子类的实例对象,然后再将父类的方法添加到这个对象上面,即“实例在前,继承在后”。ES6 的继承机制,则是先将父类的属性和方法,加到一个空的对象上面,然后再将该对象作为子类的实例,即“继承在前,实例在后”。这就是为什么 ES6 的继承必须先调用super()方法,因为这一步会生成一个继承父类的this对象,没有这一步就无法继承父类。
*/