• ES6 读书笔记


    一、let和const命令
    二、变量的解构赋值
    三、字符串的扩展
    四、数值的扩展
    五、正则的扩展
    六、数组的扩展
    七、函数的扩展
    八、对象的扩展
    九、symbol
    十、proxy和reflect
    十一、二进制数组
    十二、set和map数据结构
    十三、iterator和for...of循环
    十四、generator函数
    十五、promise对象
    十六、异步操作和async函数
    十七、Class
    十八、修饰器 (ES7 但babel支持)
    十九、module
    二十、编程风格[可参阅jscs.info]
     
    一、let和const命令
        1.1、let
                {
                    let a = 10;
                }
            仅在代码块中使用有效;
            不存在变量提升:需要在声明后使用;
            暂时性死区:只要块级作用域内存在let,其变量便绑定了该区域,不受外部影响;
            不允许重复声明:不允许相同作用域声明同一个变量;
     
        1.2、块级作用域
            由于不存在变量提升,块级作用域之间的元素互不影响。
     
        1.3、const命令
            声明常量,一旦声明,其值不能改变;
            只有声明所在的块级作用域有效;
            不存在变量提升,有暂时性死区;
            对于对象、数组等指针型变量,不能改变的是指针,而非内部内容,如果需要防止内容的改变,使用object.freeze方法。
     
        1.4、跨模块的常量
        // constants.js 模块
            export const A = 1; 
            export const B = 2;
            export const C = 3;
        // test1.js  模块
            import * as constants from ‘./constants’;
            console.log(constants.A);
         // test2.js  模块    
            import {A, B} from ‘./constatns’;
            console.log(A);
     
        1.5 全局对象属性
            window下,全局对象为window;nodejs环境下指的global对象。
            ES6下,var、function命令声明的仍为全局变量;let、const、class命令不属于全局对象属性。
     
    二、变量的解构赋值
        2.1 数组的解构赋值
            [a, b, c, d] = [1, 2, 3, 4],这种属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
            [head, …tail] = [1, 2, 3, 4] // head == 1; tail == [2, 3, 4]
            如果解构不成功,则会赋值undefined
            默认值:[x = 1, y] = [2, 3] or [x = f(), y] = [2, 3];如果默认值为表达式,仅在使用时,才会执行表达式。
     
        2.2 对象的解构赋值
            对象按照属性名取值,数组按照次序取值。
            var {foo: baz, bar: tr} = {foo:’aaa’, bar: ‘bbb’};真正被复制的是baz,而非foo;
            {x} = {x:1} //容易出错,一般会解析成代码块,最佳方式:({x}={x:1})
     
        2.3 字符串的解构赋值
            const [a, b, c, d, e] = ‘hello’;// a=‘h’,b=‘e’…
            let {length: len} = ‘hello’;// len = 5;
     
        2.4 数值与布尔值的解构赋值
            如果右边是数值或布尔值,会先转换成对象。
     
        2.5 函数参数的解构赋值
             undefined会触发函数参数的默认值。
            [1, undefined, 3].map((x = ‘yes’) => x) // [1, ‘yes’, 3]
     
        2.6 圆括号问题
            解析结构是表达式还是模式不容易,所以不要在模式中放置圆括号。
     
        2.7 用途
            a、交换变量
            b、函数返回多个值
            c、函数参数的定义
            d、提取json数据
            e、函数参数的默认值
            f、遍历map结构
     
    三、字符串的扩展
        ES6加强了对Unicode的支持,并且扩展了字符串对象。
        javascript允许采用uxxxx形式表示一个字符,其中xxxx表示字符的码点。
        3.1 字符的Unicode表示法
     
        3.2 codePointAt() 可以判断字符是否为4个字节,返回字符对应的码点
     
        3.3 string.fromCodePoint()  参数为码点,可返回字符值
     
        3.4 字符串的遍历器接口
            for (let codePoint of ‘foo’) {
                // ‘f’, ‘o’, ‘o’    其可自动识别四个字节的字符
            }
     
        3.5 at() 可返回四个字节的字符(汉字) 等价两字节的charAt()。
     
        3.6 normalize() 将字符的不同表示方法统一为同样的形式。
     
        3.7 includes(), startsWith(), endsWidth() 表示是否找到参数字符串,返回布尔值
     
        3.8 string.repeat(n) 表示将原字符串重复n次
     
        3.9 padStart, padEnd,用来补全字符串
            ‘x’.padStart(5, ‘ab’) //ababx  接受两个参数,第一个为总长,第二个为重复的字符。
     
        3.10 模板字符串
            使用反引号标识,嵌入变量${}
            $(‘#result’).append(’there are <b>${count}</b>items.’);
     
        3.11 模板编译
     
        3.12 标签模板
            可使用其嵌入其他语言,如jsx。
             函数调用的一种特殊形式,标签指函数,紧跟其后的模版字符串是参数。
            tag`hello ${a + b} world ${a * b}` => function tag([‘hello’, ‘ world’, ‘’], 15, 50)
     
        3.13 string.raw() 充当模板字符串的处理函数,返回一个反斜线都被转移的字符串。
            
    四、正则的扩展
        4.1 RegExp构造函数 new RegExp(/abc/ig, ‘i’).flag // ‘i’
     
        4.2 将四个正则方法:match、replace、search、split四个方法都定义在了RegExp的对象上
     
        4.3 u修饰符 为正则添加了u修饰符,含义为’unicode模式’
            a、点字符 .表示任意字符,对于四字节字符,无法匹配,配合修饰符u,可正确判断。
            b、unicode字符表示法 新增了大括号表示Unicode字符 /u{61}/u.test(‘a’)
            c、量词 /接{2}/u.test('接’) //true
            e、预定义模式/^S$/u.test(‘接’) // true
            f、i修饰符
     
        4.4 y修饰符 ‘粘连’修饰符 与g功能相同,不同之处y默认带^,下一位置就必须能够匹配上。
     
        4.5 sticky属性 表示是否设置了y修饰符 var r = /hello/y;  r.sticky // true
     
        4.6 flags属性 返回正则的修饰符
     
        4.7 RegExp.escape() 还未通过审核
     
    五、数值的扩展
        5.1 二进制和八进制数值表示法
            0b || 0B 为二进制; 0o || 0O表示八进制
     
        5.2 Number.isFinite(), Number.isNaN() 分别用来检查 Infinite 和 NaN这两个特殊值。
            传统的这两个方法,会先调用Number()转为数字,在判断;而新方法不转换,直接判断。
     
        5.3 Number.parseInt(), Number.parseFloat() 其行为不变,只是移植到了Number对象上。
     
        5.4 Number.isInteger()用来判断是否为整数,3和3.0视为同一值。
     
        5.5 Number.EPSILON 一个极小的常量,为了减小浮点数相减的误差而设,如果误差小于这个常量,则正确。
            5.5545656563e-17 < Number.EPSILON
     
        5.6 安全整数和Number.isSafeInteger()  
            ES6提供了两个常量,Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER
     
        5.7 Math对象的扩展
            增加了17个与数学相关的方法。
            a、Math.trunc() 去除数字的小数部分,返回整数部分。
            b、Math.sign() 判断一个数是正数、负数还是零,+1正数;-1负数;+0; -0; NaN
            c、Math.cbrt() 计算一个数的立方根
            d、Math.clz32() 返回一个32位无符号整数形式(使用二进制表示的)有多少个前导0
            e、Math.imul() 返回两个数以32位带符号整数相乘的结果
            f、Math.fround() 返回一个数的单精度浮点数形式
            g、Math.hypot() 返回所有参数的平方和的平方根
            对数方法:
            h、Math.epm1(x) 返回e^x-1
            i、Math.log1p(x) 返回 1/ln(1+x)
            j、Math.log10(x) 返回10为底的x的对数 Math.log10(10000) //4
            k、Math.log2(x) 返回以2为底x的对数
            三角函数方法:
            l、Math.sinh(x)   返回x的双曲正弦
            m、Math.cosh(x) 返回x的双曲余弦
            n、Math.tanh(x)    返回x的双曲正切
            o、Math.asinh(x)    返回x的反双曲正弦
            p、Math.acosh(x)    返回x的反双曲余弦
            q、Math.atanh(x)    返回x的反双曲正切
      5.8 指数运算符 **
       2 ** 3 = 8
     
    六、数组的扩展
        6.1、Array.from() 将两类对象转换成真正的数组:类数组的对象及可遍历的对象(即必须有length属性)
            如dom操作的nodeloost集合、函数内部arguments对象及ES6的Set和Map方法
            document.querySelectorAll(‘p’)
            tips: 运算符...也可将某些结构转换成数组;from能正确的识别unicode字符
            Array.from(spans, s => s.textContent);其转换数组的同时,具备map的功能。
     
        6.2、Array.of()
            用于将一组值转换为数组。Array.of(3, 11, 8) // [3, 11, 8]
     
        6.3、copyWithin(target, start = 0, end = this.length)
            将数组内部指定位置的成员复制到其他位置上
     
        6.4、find()和findIndex()
            find找出第一个符合条件的数组成员,返回成员或者undefined
            [1, 4, -5, 10].find((n) => n<0) //-5
            findIndex()与上同,返回成员位置,否则返回-1
     
        6.5、fill(x, start, end)
            填充数组[‘a’, ‘b’].fill(7, 1, 2) // [‘a', 7]
     
        6.6、 entries()、keys()、values() 
            用于遍历数组,返回一个遍历器对象,可用for..of遍历
            entries为遍历键值对;keys为遍历键值;values为遍历值
            for (let [index, elem] of [‘a’, ‘b’].entries()) // 0 ‘a’
     
        6.7、includes(x, start, end)
            返回一个布尔值,表示某个数组是否包含给定的值
     
        6.8、数组的空位
            [, , ,]空位不代表undefined
            ES5对空位的处理不一致,而ES6进行统一,将空位都转换为undefined,空位不会被忽略掉。尽量避免空位出现。
     
        6.9、数组推导
            var a1 = [1, 2, 3,4];
            var a2 = [for (i of a1) i* 2]; //[2, 4, 6, 8]
            var a3 = [for (i of a1) if (i > 2) i]; //[3, 4]
            其可替代map()及filter()方法
     
    七、函数的扩展
        7.1、函数参数的默认值
             function log(x, y = ‘hello’){}
            a、参数的解构赋值:重点区分参数的默认值与解构赋值的默认值。
            b、默认参数:非显示的输入undefined,触发该参数等于默认值,null没有这个效果。
            c、length属性:指定默认值的参数,不计入length,导致length失真。
            d、作用域:当前函数作用域与全局作用域
                try catch err throw
     
        7.2、rest参数 “…变量名”
            rest参数搭配的变量是一个数组,将多余的参数放入其中;rest参数之后不能再有参数。
     
        7.3、扩展运算符
            ‘…’,将一个数组转为用逗号分隔的参数序列。
            a、替代apply()
            b、合并数组:[1, 2, …more]
            c、与解构赋值结合:[1, 2, …rest] = list;     
                tips:扩展运算符用于数组赋值时,只能放在末尾。
            d、字符串:[…’hello’] //[‘h’, ‘e’, ‘l’, ‘l’, ‘o’]
                可正确返回字符的长度(可识别unicode字符);[...string].length
            e、类数组对象:可转变成数组.
     
        7.4、name属性
            function foo(){} foo.name // “foo"
     
        7.5、箭头函数
            使用箭头定义函数;
            a、var f = v => v;  等同于 var f = function(v) {return v};
            b、函数不需要参数或者需要多个参数,就用()代替:
                 var f = () => v;  等同于 var f = function(a, b) {…… return v};
            c、由于大括号被解析成代码块,如果需要返回对象,需要加上括号:
                var fun = id => ({id: id, name: ‘hity’});
            d、如果代码块多余一条语句,就需要用大括号包起来。
            e、嵌套箭头函数
            tips:
                a、函数体内的this,是定义时的对象,而非运行时;
                b、不可当构造函数;
                c、arguments对象不存在,可用rest参数代替;
                d、不可使用yield命令,无法用作generator函数;
                e、箭头函数无自己的this作用域,this指向父级this;所以无法使用apply、call、bind改变this指向
                f、无arguments、super、new.target;
     
        7.6、函数绑定
                ‘::’可以将左边对象作为上下文绑定到右边的函数上。可以采用链式的写法,返回的还是原对象。
     
        7.7、尾调用优化
                概念:指某个函数的最后一步是调用另外一个函数:function f(x){ return g(x);}
                尾调用优化,去掉外层的调用帧。
                    tips:仅当内部函数不需要使用外部函数的变量时,优化才会进行。
                尾递归:递归非常消耗内存,将其转变为尾递归将只有o(1)的复杂度。
                    tips:尾递归仅严格模式下可用:“use strict”,这种情况下函数的信息都将移除~
      
    八、对象的扩展
        8.1、属性的简洁表示法
            {x, y} == {x: x, y: y};
            var obj = {
                birth,
                method() {
                    return ‘hello';
                }
            }
     
        8.2、属性名表达式
            let obj = {
                [prop]: true,
                [‘a’ + ‘b’]: 123
            }
     
        8.3、方法的name属性
            (new Function()).name //anonymous
            bind创造的方法,name属性返回“bound”加原函数名。
     
        8.4、Object.is()
            比较两个值是否严格相等。与 === 基本一致。(+0, -0)//false  (NaN, NaN)// true
     
        8.5、Object.assign(targetObj, srcObj)
            作用:将srcObj的所有可枚举对象复制到targetObj上;其只复制自身属性,不可枚举的和继承的不会被复制。
     
        8.6、属性的可枚举性
            object.getOwnPropertyDescriptor(obj, ‘foo’);
            // {value: 123, writable: true, enumerable: true, configurable: true}
            有三个操作会忽略enumerable为false的属性:
                a、for…in:遍历自身和继承的可枚举属性;
                b、Object.keys():返回对象自身的可枚举属性键名;
                c、JSON.stringify():串行化对象自身的可枚举属性;
                d、Object.assign():复制自身可枚举的属性;
                e、Reflect.enumerate():返回所有for...in循环会遍历的属性
            tips:所有Class的原型的方法都不可枚举。
     
        8.7、属性的遍历
            ES6共6种方法遍历对象的属性:
            for…in:(无symbol)
            Object.keys():(无symbol)
            Object.getOwnPropertyNames(obj):返回数组,包含对象自身所有属性(无symbol)
            Object.getOwnPropertySymbols(obj):返回数组,包含对象自身的所有symbol属性
            Reflect.ownKeys(obj):返回数组,包含对象自身所有的属性
            Reflect.enumerate(obj):返回一个Iterator对象,遍历对象自身和继承所有可枚举属性(无symbol)
     
        8.8、__proto__属性、Object.setPrototypeOf()、Object.getPrototypeOf()
            __proto__属性用来设置、读取当前对象的prototype对象;但最好不用,而是使用object.setPrototypeOf(object, prototype)、object.getPrototypeOf()、object.create()代替。
     
        8.9、对象的扩展运算符
            rest亦可用于对象,使用方法相同。
            tips:
                a、其为浅复制,如果一个键的值为复合类型,则复制这个值的引用。
                b、不能复制继承自原型对象的属性。
                c、rest对象中存在取值函数get,这个函数会立即执行。
     
    九、symbol
        9.1、概述
            引入的原因:解决扩展他人对象属性时的命名冲突。
            javascript的第7种数据类型为:symbol,属性名属于symbol就是独一无二的。
            tips:symbol值不能与其他值运算,它不能添加属性,类似字符串。
                 symbol值可转为字符串、布尔值;
     
        9.2、作为属性名的symbol
            a {[mySymbol]:  ‘hello’}
     
        9.3、消除魔术字符串
            指在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数字。
     
        9.4、属性名的遍历
            可以设置一些非私有又希望仅内部使用的方法。
     
        9.5、symbol.for(), symbol.keyFor()
            symbol.for(name):查找对应的symbol,查到则返回,并登记在全局中,否则创建一个新的symbol。
            symbol.keyFor(s1):返回已登记的symbol key(即name)。
     
        9.6、内置的symbol值
            
    十、Proxy和Reflect
        proxy代理,可以理解成目标对象前架设一“拦截”层,外界访问必须先通过该拦截。
        new Proxy(target, handle);
        10.1、实例方法
            a、get():用于拦截某个属性的读取操作;
            b、set():用于拦截某个属性的赋值操作;
            c、apply(): 用于拦截函数的调用、call和apply操作;
            d、has(): 用于隐藏某些操作,不被in操作符发现;
            e、construct(): 用于拦截new命令;
            f、deleteProperty: 用于拦截delete操作,使得属性不被delete;
            g、defineProperty:用于拦截object.defineProperty(添加新属性)操作;
            h、enumerate():用于拦截for...in循环;
            i、getOwnPropertyDescriptor():用于拦截object.getOwnPropertyDescriptor;
            j、getPrototypeof():用于拦截其运算,以及其他一些操作;
            k、isExtensible():用于拦截其操作;[如果对象是可扩展的(这表示可向对象添加新属性),则为 true;否则为 false。]
            l、ownKeys():用于拦截object.keys操作;
            m、preventExtensions():用于拦截其操作,必须返回布尔值;
            n、setPrototypeOf():用于拦截其方法。
     
        10.2、proxy.revocable()
            返回一个可取消的proxy实例。
     
        10.3、reflect概述
            其设计目的:
            a、将object上明显属于语法层面的方法放到reflect上;
            b、修改某些object的返回结果,让其变得更合理;
            c、让object操作都变成函数行为;
            d、reflect对象的方法与proxy对象的方法一一对应,这样可以直接让proxy对象调用reflect对象完成默认行为。
     
    十一、二进制数组(大略的过,需要理解内存之类的计算机原理等)
        设计目的:为了让开发者能够通过javascript与操作系统的原生接口进行二进制通信。
        二进制数组分三类:
        a、arrayBuffer对象:代表原始的二进制数据;
        b、typedArray视图:用于读写简单类型的二进制数据;
        c、dataView视图:用于读写复杂类型的二进制数据。
        typedArray有九种类型数据:int8、uint8、uint8C、int16、uint16、int32、uint32、float32、float64
        dataView有除uint8C外的八种数据类型。
        API用到了二进制数组操作二进制数据的有一下浏览器:
            File API、XMLHttpRequest、Fetch API、Canvas、WebSocket
     
        11.1、arrayBuffer对象
            var buf = new ArrayBuffer(32);
            arrayBuffer.prototype.byteLenth:由于分配内存的操作不一定成功,所以需要通过该字段来判断是否成功;
            arrayBuffer.prototype.slice():允许将内存区域的一部分复制生成一个新的arrayBuffer对象;
            arrayBuffer.isView():返回布尔值,表示参数是否为arrayBuffer的一个试图实例。
     
        11.2、typedArray视图
            其有九个构造函数,对应不同的数据类型;
            形成的数组成员都是一种类型;
            成员都是连续的,不会有空位;
            默认值为0。
     
        11.3、dataView视图
     
        11.4、二进制数组的应用
            a、ajax 返回的类型可以为二进制,设置为arraybuffer or blob;
            b、canvas 类型值为uint8clampedarray
            c、websocket 通过arraybuffer发送或者接收二进制数据;
            d、fetch API 取回的数据为arrayBuffer对象;
            e、file API 如果知道文件为二进制数据类型,也可以将其读取为arrayBuffer对象。
     
    十二、set和map数据结构
        12.1、set
        set是一种新的数据结构,其与数组的区别是,没有重复值,成员值都唯一。set本身为构造函数。
        set接受一个数组作为参数,var set =new Set([1, 2, 3, 4, 4]); // [1, 2, 3, 4]。
        set加入的值,不会进行类型转换,判断相等使用的是 ===。 
        set实例的属性和方法:
            set.prototype.size: 返回set成员的总数;
            add(value): 添加某个值,返回set结构本身;
            delete(value):删除某个值,返回一个布尔值;
            has(value): 返回一个布尔值;
            clear():清除所有成员,没有返回值。
        遍历方法:keys()、values()、entries()、forEach()
     
        12.2、weakSet
            为不重复的值的集合,与set的区别:
                a、其成员只能是对象;
                b、其对象为弱对象,垃圾回收机制不考虑它的引用,因此,它是不可遍历的。
            方法:add()、delete()、has();
            其用处为:储存DOM节点,而不用担心这个节点从文档中移除时会发生内存泄漏。
     
        12.3、map
            map类似对象,区别在于键不同,对象的键限制只允许字符串,map的键不受限:
                对象为“字符串-值”的对应,map为“值-值”的对应。
            需要堤防一种情况,键为引用地址的情况:如
                map.set([‘a’], 123);
                map.get([‘a’]); // undefined
                由于数组作为键时,标记的是数组所在的引用地址。
                var k1 = [‘a’];
                map.set(k1, 1234);
                map.get(k1) // 1234
            map的键是跟内存绑在一起的,只要内存地址不一样,就视为两个键。如此解决了同名属性碰撞的问题。
            map的属性和方法:
                size属性:返回成员总数;
                set(key, value):设置键值,并返回整个map的结构;
                get(key):读取key对应的值,找不到则返回undefined;
                has(key):返回布尔值,确认键是否存在;
                delete(key):删除某个键,返回布尔值;
                clear():清除所有成员,没有返回值。
            遍历方法:keys()、values()、entries()、forEach()。
            可使用运算符(...)转换成数组。
            转换:
                a、map转数组(…)
                b、数组转map;
                c、map转对象;
                d、对象转为map;
                e、map转为son(键名为字符串);
                f、json转为map(键名为字符串)。
     
        12.4、weakmap
            weakmap与map类似,但其只接受对象作为键名,键名指向的对象不计入垃圾回收机制。其有助于内存泄漏。
     
    十三、iterator和for...of循环
        iterator接口为各种不同的数据提供统一的访问机制。只要部署iterator接口,就可完成遍历操作。
        作用:
            a、为各种数据结构提供统一的、简便的访问接口;
            b、使得数据结构的成员能够按照某种次序排列;
            c、es6创造了一种新的遍历命令for...of循环,iterator接口主要供其消费。
        遍历过程:
            step1、创建指针对象,指向当前数据结构的起始位置;
            step2、第一次调用指针对象的next方法,指向第一个成员;
            step3、第二次调用next方法,指向第二个成员;
            step4、不断调用,直到结束。
        step2时,会返回数据结构当前的成员信息;具体是返回一个包含value和done的对象,value为成员值,done为布尔值,表示遍历是否结束。
        iterator接口需要通过symbol.iterator来部署。
     
        13.3、调用iterator接口的场合
            解构赋值、扩展运算符、其他场合:for...of、array.from()、map()、set()、weakmap()、weakest()、promise.all()、promise.race()。
     
        13.4、字符串的iterator接口
            var string = “lala”;
            var iterator = string[Symbol.iterator]();
            修改遍历器对象。
     
        13.5、iterator接口与generator函数
            Symbol.iterator方法最简单的实现还是generator函数。
     
        13.6、遍历器对象的return()、throw()
            next方法是必须部署的方法,return方法用于for...of循环提前退出时(break、continue或者出错),调用。return方法必须返回一个对象。throw方法配合generator使用。
     
        13.7、for...of循环
            一个数据结构只要部署了Symbol.iterator属性,就可以用for...of循环遍历其成员。
            for… in、for…of
            数组、set、类数组对象[string]:for (let v of arr)
            map:for (var [name, value] of  es6)
     
    十四、generator函数
        14.1、简介
            基本概念:Generator函数为ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。
            Generator是状态机,也是遍历器对象生成器,返回一个遍历器对象。它的两个特征:a、function命令与函数名之间有一个星号;b、内部使用yield定义内部状态。最大特点,暂缓执行函数;通过next做暂缓和停顿。
            其调用后,不执行,而是返回一个iterator对象,需用next方法调用,才执行。
            yield语句无法用在普通函数中,否则出错;且用于表达式中时,需要放在圆括号内。
     
        14.2、next方法的参数
            next方法的参数为yield的执行结果,可向函数体内注入值。
            yield返回值通常为undefined;如果next带有参数,则返回该参数。next传递的参数往往为上一次yield的返回值。
     
        14.3、for…of循环
     
        14.4、Generator.prototype.throw(),可在函数体外抛出错误,函数体内执行。
     
        14.5、Generator.prototype.return()
            可返回给定的值,并终结Generator函数的遍历。
            g.return(“foo”) //{value: “foo”, done:true}
            如果函数内部有try...finally代码块,那么return方法会推迟到finally代码执行完再执行。
     
        14.6、yield语句
            如果Generator函数内部调用另一个Generator函数,默认情况下无效;使用yield*,则生效。yield*表示在函数内部部署了一个for...of循环。
     
        14.7、作为对象属性的Generator函数
            let obj = {
                * myGeneratorMethod() {}
            }
     
        14.8、Generator函数的this
            构造函数返回的是一个内部的指针,可通过bind一个对象,赋予作用域,将this绑定在对象上。
     
        14.9、Generator函数推导
            let squard = (for (n of generator()) n * n);
     
        14.10、含义
            Generator与状态机,其本身包含状态机,不需要额外的外部变量保存状态。
     
        14.11、应用
            a、异步操作的同步表达
                function* main() {
                    var result = yield request(url);
                    var resp = JSON.parse(result);
                }
     
                function request(url) {
                    makeAjaxCall(url, function(response) {
                        it.next(response);
                    });
                }
     
                var it = main();
                it.next();
            b、控制流管理
            c、部署iterator接口
                    利用Generator函数可以在任意对象上部署Iterator接口。
            d、作为数据结构
                其可以返回一系列的值。
     
    十五、promise对象
        15.1、promise的含义
            所谓promise就是一个对象,用来传递异步操作的消息。其有两个特点:
                a、其状态不受外界影响;其有三种状态:pending(进行中)、resolved (已完成,又称”fulfilled”)、rejected(已失败);
                b、一旦状态改变就不会再变,任何时候都可以得到这个结果;
            有了promise对象就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调。
            缺点:
                无法取消promise;如果不设置回调,promise内部抛出的错误不会反应到外部;一般说来,如果事件不断发生,使用stream模式比部署promise更好。
     
        15.2、基本用法
                两个异步之间的调用:
                    var p1 = new Promise(function (resolve, reject){})
                    var p2 = new Promise(function (resolve, reject){
                        resolve(p1);
                    })
                p2的状态为(p1 与 p2)的并集。只要一个为rejected,则为rejected;全部为resolved则为resolved。
     
        15.3、Promise.prototype.then()
            then方法返回一个promise实例(并非前一个实例),此时可以链式的调用then。
     
        15.4、Promise.prototype.catch()
            其是.then(null, rejection)的别名,用于指定发生错误的回调函数;promise在resolve后再抛出错误,并不会被捕获。
            promise的错误具有“冒泡”性质,会一直向后传递,直到捕获为止。最好不在then的第二个参数定义rejected状态的回调,而应使用catch方法。
            catch方法也是返回一个promise实例。
     
        15.5、promise.all()
            promise.all方法用于将多个promise实例包装成一个新的promise实例。
            var p = Promise.all([p1, p2, p3]);其参数必须具有iterator接口,且返回的每个成员都是Promise实例。
            p的状态为:
                a、三者都为resolved,则它为resolved;
                b、只要一个为rejected,则它为rejected;此时第一个被rejected的实例的返回值会传递给回调函数。
     
        15.6、promise.race()
            亦是将多个promise实例包装成一个新的promise实例。只要其中有一个实例改变状态,p的状态也跟着改变。
     
        15.7、promise.resolve()
            其可将现有对象转为promise对象;
            promise.resolve(‘foo’) 等价于 new Promise(resolve => resolve('foo’));
     
        15.8、promise.reject()
            返回一个promise的实例,状态为rejected。
     
        15.9、两个附加方法
            done():为了最终捕获任何可能出现的错误;
            finally():指定不管promise对象最后状态如何都会执行的操作。
     
        15.10、应用
            a、加载图片
            b、Generator与Promise(管理 流程+异步 混合操作)
     
        15.11、async函数(亦是用于取代回调函数解决异步操作)
     
    十六、异步操作和async函数
        在ES6诞生前,异步编程的方法大概有4种:
            a、回调函数;
            b、事件监听;
            c、发布、订阅;
            d、promise对象。
            
        16.1、Generator函数
            协程,类似线程,执行到一半转移执行权。yield命令将执行权交给其他协程。
            其数据交换及错误处理:next(x);try{}catch{}.
            fetch返回promise对象。
     
        16.2、thunk函数(结合generator函数进行自动流程管理)
            编译器的“传名调用”,将参数放到一个临时函数中,再将临时函数传入函数体内。这个临时函数就叫thunk函数。
     
        16.3、co模块
            co模块用于Generator函数的自动执行。
            var co = require(‘co’);
            co(gen);
            co(gen).then(function() {
                console.log(‘generator函数执行完毕');
            });
            如何交回generator的执行权:
                a、回调函数。将异步包装成thunk函数,在回调函数中交回执行权。
                b、promise对象。将异步操作包装成promise对象,用then 方法交回执行权。
            co模块是将两种自动执行器包装成了一个模块,使用co的前提条件是,yield命令后面只能是thunk函数活着promise对象。
     
        16.4、async函数(属于es7)
            async函数:
                a、内置执行器;
                b、更好的语义;
                c、更广的适应性,async函数的await命令后面可以使promise对象和原始类型值;
                d、返回值为promise对象。
     
    十七、Class
        17.1、基本语法
            定义类:
                class Point {
                    constructor(x, y) {
                        this.x = x;
                        this.y = y;
                    }
     
                    toString() {
                        return ‘(‘ + this.x + ‘, ‘ + this.y + ‘)’;
                    }
                }
        类的数据类型就是函数,类本身就指向构造函数。
        类的内部定义的所有方法都是不可枚举的。
        不存在变量提升。
     
        17.2、class的继承
            class之间通过extends关键字实现继承;通过super方法,指向父类的this对象。
            class ColorPoint extends Point {
                constructor(x, y, color) {
                    super(x, y); //调用父类的constructor(x, y)
                    this.color = color;            
                }
            }
        es5的继承实质上是先创造子类的实例对象this,然后再将父类的方法添加到this上(parent.apply(this));
        es6的继承实质上是先创建父类的实例对象this(调用super方法),然后再用子类的构造函数修改this。
        类的prototype属性和__proto__属性:
            a、子类的__proto__属性表示构造函数的继承,指向父类;
            b、子类的prototype的__proto__属性表示方法的继承,指向父类的prototype属性。
        extends的继承目标:
            只要具有prototype属性,就能被继承。
            object.getPrototypeOf()方法从子类上获取父类。
            super关键字代表父类的实例。
     
        17.3、原生构造函数的继承
            es5无法继承,es6可以。
     
        17.4、class的取值函数(getter)和存值函数(setter)
            与es5一样,在class内部可以使用get和set关键字对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
     
        17.5、class的generator方法
            class Foo {
                constructor(…args) {
                    this.args = args;
                }
                *[Symbol.iterator]() {
                    for (let arg of this.args) {
                        yield arg;
                    }
                }
            }
        
            for (let x of new Foo(‘hello’, ‘world’)) {
                console.log(‘x');
            }
     
            // hello //world
     
        17.6、class的静态方法
            定义:在一个方法上加static关键字,就表示该方法不会被实例继承,而是直接通过类调用,成为“静态方法”。
            通过使用extends,可以让实例继承。
     
        17.7、class的静态属性
            定义:指class本身的属性,而不是定义在实例对象(this)上的属性。
     
        17.8、new.target属性
            new是从构造函数生成实例的命令。该属性可以确定构造函数是怎么调用的。
            function Person(name) {
                if (new.target === Person) {
                    this.name = name;
                } else {
                    throw new Error('必须使用new生成实例’);
                }
            }
            var person = new Person(‘hit') //正确
            var notAPerson = Person.call(person, ‘张三’); // 报错
     
        17.9、mixin模式的实现
            定义:将多个类的接口“混入”另一个类:
            
    十八、修饰器 (ES7 但babel支持)
        18.1、类的修饰器
            @testable
            class MyTestableClass {}
            其中的@testable为修饰器,修改了类的行为,增加了一个静态属性。
     
        18.2、方法的修饰
            class Person {
                @readonly
                name() {
                    return `${this.first} ${this.last}`
                }
            }
            修饰器函数共接受3个参数,修饰的目标对象;修饰的属性名;属性的描述对象。
            function readonly(target, name, descriptor) {
                descriptor.writable = false;
                return descriptor;
            }
     
            Object.definePrototype(Person.prototype, ’name’, descriptor);
     
        18.3、为何修饰器不能用于函数
            修饰器职能用于类及类的方法,因为其存在函数提升。
     
        18.4、core-decorators.js
            其是一个第三方模块,提供了几个常见的修饰器。
            a、@autobind 使得方法中的this对象绑定原始对象。
            b、@readonly使得属性或者方法不可写;
            c、@override检查子类方法是否正确覆盖父类的同名方法;
            d、@deprecate在控制台显示一条警告,表示该方法将废除;
            e、@suppressWarnings 修饰器抑制decorated修饰器导致的console.warn调用。
     
        18.5、使用修饰器实现自动发布事件
            “发布/订阅”库postal.js
     
        18.6、mixin
            在修饰器的基础上可以实现mixin模式,就是对象继承的一种替代方案,在对象中混入另一个对象的方法。
     
        18.7、trait
            效果与mixin类似,但提供更多的功能,比如防止同名方法的冲突、排除混入某些方法、为混入的方法起别名等。第三方模块:traits-decorator。
     
    十九、module
        ES6的class只是面向对象编程的语法汤,升级了ES5构造函数的原型链继承的写法,并没有解决模块化问题。
        commonjs模块是对象,输入时必须查找对象属性,其实质是整体加载模块,然后使用方法,这种为“运行时加载”。
        es6模块不是对象,而是通过export命令显示的制定输出的代码,输入时采用静态命令的形式。
        import{ start, exists, readFile} from ‘fs’;
        以上实质是从fs模块加载3个方法,其他方法不加载。这种加载称为“编译时加载”
        效率比commonjs高。
        ES6模块化的其他优点:
            a、不再需要UMD模块格式;
            b、将来浏览器的新API可以用模块格式提供,不再需要做成全局变量或者navigator对象的属性;
            c、不再需要对象作为命名空间,未来这些功能可通过模块实现。
        19.1、严格模式 [lottery插件完成后做详细了解]
            模块化自动采用严格模式,限制如下:
                a、变量必须声明后使用;
                b、函数的参数不能有同名属性,否则报错;
                c、不能使用with语句;
                d、不能对只读属性赋值,负责报错;
                e、不能使用前缀0表示八进制,否则报错;
                f、不能删除不可删除的属性,否则报错;
                g、不能删除变量(delete prop),会报错,职能删除属性(delete global[prop]);
                h、eval不会再外层作用域引入变量;
                i、eval和arguments不能被重新赋值;
                j、arguments不会自动反映函数参数的变化;
                k、不能使用arguments.callee;
                l、不能使用arguments.caller;
                m、禁止this指向全局变量;
                n、不能使用fn.caller和fn.arguments获取函数调用的堆栈;
                o、增加保留字段(protected、static和interface)。
     
        19.2、export命令
            模块功能主要由两个命令构成:export和import;export用于规定模块的对外接口;import命令用于输入其他模块提供的功能。
            // profile.js
            export { f1 as firstName, lastName, year};
     
        19.3、import命令
            import {firstName as f1, lastName, year} from ‘./profile’;
     
        19.4、模块的整体加载
            除了指定加载某个输出值,还可以使用整体加载,即用(*)指定一个对象,所有输出值都加载在这个对象上。
            import * as circle from ‘./circle’。
     
        19.5、module命令
            module可取代import命令,达到整体输入模块的作用。
            module circle from ‘./circle’。
     
        19.6、export default命令
            export default function() {};
            import cc32 from ‘crc32’;
        vs
            export function cc32() {};
            import {crc32} from ‘crc32’;
            留意大括号的区别(“{}”)。
     
        19.7、模块的继承
            export * from ‘circle’
            表示输出circle模块的所有属性和方法。
     
        19.8、ES6模块加载的实质
            ES6模块加载机制与commonjs模块完全不同。commons模块输出的是一个值的拷贝,而ES6模块输出的是值的引用。
     
        19.9、循环加载
            commonjs模块的加载原理:加载时执行,即代码在require 时就会全部执行;一旦出现“循环加载”,就只输出已经执行的部分,还未执行的部分不输出。
            ES6模块是动态引用,遇到模块加载命令import时不会去执行模块,只是生成饮用,开发者自己保证取值时能够真正取到值。
     
        19.10、ES6模块的转码
            除babel可以转外,一下两种方法也可以:
            a、ES6 module transpiler
            b、systemJS 
     
    二十、编程风格[可参阅jscs.info]
        20.1、块级作用域
            let 取代 var;
            全局常量和线程安全:建议使用const而非let;
     
        20.2、字符串
            一律使用单引号或者反引号;const b = `foo${a}bar`;
     
        20.3、解构赋值
            数组成员对变量赋值,优先解构赋值。
     
        20.4、对象
            a、单行定义的对象,最后一个成员不以逗号结尾。多行定义的对象需要。
            b、对象尽量静态化,一旦定义,就不得随意添加新的属性。
                const a = {x: null};
                a.x = 3;
            c、如果对象属性名是动态的,在创建时,使用属性表达式定义。
                const obj = {
                    id: 5,
                    [getKey(‘enabled’)]: true
                }
            d、对象的属性和方法尽量采用简洁表达法,易于描述和书写:
                const atom = {
                    ref, //ref: ref
                    addValue(value) {
                        return atom.value + value;
                    }
                }
     
        20.5、数组
            使用扩展运算符(...)复制数组。
            const itemsCopy = […list];
     
        20.6、函数
            a、立即执行函数使用箭头函数
                (() => {
                    console.log(‘Welecome to the Internet.');
                })();
            b、使用函数表达式的场合,使用箭头函数
                [1, 2, 3].map([x] => {
                    return x*x;
                })
            c、箭头函数代替Function.prototype.bind,不应再用self/_this/that绑定this.
                const boundMethod = (…params) => method.apply(this, params);
            d、简单的、单行的、不会复用的函数,建议采用箭头函数。
            e、所有配置项都应该集中在一个对象,放在最后一个参数,布尔值不可以直接作为参数:
                function divide(a, b, {option = false} = {})
            f、不再函数体内使用arguments变量,使用(…)代替:
                function all(…args) {
                    return args.join('');
                }
            g、默认值语法设置函数参数的默认值:
                function handle(opts = {}){}
     
        20.7、map结构
            注意区分object和map,如果只是需要key:value的数据结构,则使用map。
     
        20.8、class    
            a、用class取代需要prototype的操作。
            b、使用extends实现继承
     
        20.9、模块
            a、module语法是javascript模块的标准写法,使用import取代require;
            b、使用export取代module.exports;
            c、export default不要与普通export同时使用;
            d、不要再模块输入中使用通配符*;
     
        20.10、eslint的使用
            其是一个语法规则和代码风格检查工具,可以确保语法正确、风格统一。        
  • 相关阅读:
    创建分区表(按照年份分区,自动新增分区)
    flash rock me
    苹果有虫才好吃
    Evolutility改造支持oracle
    Nhibernate问题三则
    Html5+razor+jqmobile尝鲜
    配置Instantclient
    T4,Redmine,Nhibernate etc
    monotouch开发ios应用手记
    大文件及文件夹上传(续)
  • 原文地址:https://www.cnblogs.com/hity-tt/p/6511019.html
Copyright © 2020-2023  润新知