es6新增

一、Decorator 修饰器
 
> 用来修改类的行为

        // mixins.js
        export function mixins(...list) {
            return function (target) {
                Object.assign(target.prototype, ...list)
            }
        }
        // main.js
        import { mixins } from './mixins'

        const Foo = {
        foo() { console.log('foo') }
        };

        @mixins(Foo)
        class MyClass {}

        let obj = new MyClass();
        obj.foo() // 'foo'

        // 用Object.assign 模拟
        const Foo = {
        foo() { console.log('foo') }
        };

        class MyClass {}

        Object.assign(MyClass.prototype, Foo);

        let obj = new MyClass();
        obj.foo() // 'foo'



最新提案

> 1. do表达式: 返回内部最后执行的表达式的值

        let x = do {
            let t = f();
            t * t + 1;
        };

        return (
        <nav>
            <Home />
            {
            do {
                if (loggedIn) {
                <LogoutButton />
                } else {
                <LoginButton />
                }
            }
            }
        </nav>
        )

> 2. throw 可用于表达式了,之前只能用于命令

        console.log(throw new Error());
        this._id = value || throw new Error("Invalid value");

> 3. 链判断运算符

        const firstName = message?.body?.user?.firstName || 'default';
        a?.b
        // 等同于
        a == null ? undefined : a.b

        a?.[x]
        // 等同于
        a == null ? undefined : a[x]

        a?.b()
        // 等同于
        a == null ? undefined : a.b()

        a?.()
        // 等同于
        a == null ? undefined : a()


> 4. 函数的部分执行:?是单个参数的占位符,...是多个参数的占位符

        let obj = {
        f(x, y) { return x + y; },
        };

        const g = obj.f(?, 3);
        g(1) // 4

> 5. 管道运算符

        // 传统的写法
        exclaim(capitalize(doubleSay('hello')))
        // "Hello, hello!"

        // 管道的写法
        'hello'
        |> doubleSay
        |> capitalize
        |> exclaim
        // "Hello, hello!"

> 6.BigInt数据类型:大于或等于2的1024次方的数值,JavaScript 无法表示,会返回Infinity;BigInt 只用来表示整数,没有位数的限制,任何位数的整数都可以精确表示。

        const a = 2172141653n;
        const b = 15346349309n;

        // BigInt 可以保持精度
        a * b // 33334444555566667777n

        // 普通整数无法保持精度
        Number(a) * Number(b) // 33334444555566670000

> 6. BigInt对象

        BigInt(123) // 123n
        BigInt('123') // 123n
        BigInt(false) // 0n
        BigInt(true) // 1n
        // BigInt()构造函数必须有参数,而且参数必须可以正常转为数值,下面的用法都会报错。
        BigInt('123n') // SyntaxError
        BigInt('abc') // SyntaxError

module加载规则

> 默认情况下,浏览器是同步加载 JavaScript 脚本,即渲染引擎遇到script标签就会停下来,等到执行完脚本,再继续向下渲染。<br/>
> 异步加载:给script加defer和async属性;渲染引擎遇到这步就会开始下载,同时页面继续渲染;defer是等到页面正常渲染完后执行。async一旦下载完脚本,浏览器就会中断渲染,立即执行此脚本

        <script src="path/to/myModule.js" defer></script>
        <script src="path/to/myModule.js" async></script>

> ES6 将script的type属性设置为module,所以浏览器知道了这是es6模块;便执行异步加载,页面渲染完在执行,不会造成浏览器拥堵。

        <script type="module" src="./foo.js" async></script>

> 对于ES6模块,有几点默认:

* 1. 代码在模块作用域之中运行,而不是在全局作用域运行,模块内的变量,外部不可见。
* 2. 脚本自动采用严格模式, 不管有没有声明use strict。
* 3. 模块中顶层的this返回undefined,而不是指向window

> ES6模块与commonJS模块的差异
* 1. commonJS模块输出的是一个值得拷贝,不会被后面修改,ES6模块输出的是值得引用,可被重新赋值。
* 2. commonJS模块是运行时加载,ES6模块是编译时输出接口。因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。



class 类

        function Point(x,y){
            this.x = x;
            this.y = y;
        }

        Point.prototype.toString = function(){
            return '(' + this.x + ',' + this.y + ')';
        }

        var p = new Point(2,4);

> 类似 class类相当于构建了一个构造函数

        class Bar {
            doStuff(){
                console.log('stuff');
            }

            constructor(props) {
                super(props); //super作为一个关键字,指向原型对象时 可直接调用 super.XXX
                //....
            }
        }

        var b = new Bar();
        b.doStuff() //stuff
        b.constructor === Bar.prototype.constructor(直接指向类的本身Bar) //这些类的方法都定义在prototype上面

> 由于类的方法都定义在prototype上,可以通过Object.assign()向原型链上添加方法

        Object.assign(Point.prototype,{
            toString(){},
            toLower(){}
        })

> 类的内部所有定义的方法都是不可枚举的

        Object.keys(Point.prototype) // []
        Object.getOwnPropertyNames(Point.prototype) // ['constructor','toString']

> constructor(){}
> constructor()方法是类的默认方法,1.new生成的实力对象的同时就自动调用constructor方法<br/>
>2.其默认返回的是实力对象本身(this),而不是原型对象的属性

        class Self {
            constructor(x,y){
                this.x = x; //this默认指向 类的实例,若单独提出来则指向当前运行环境,采取绑定或尖头函数
                this.y = y;
            }

            toString(){
                return '('+this.x + ',' + this.y + ')';
            }
        }

        var self1 = new Self(2,3);
        self1.toString(); //(2,3)
        self1.hasOwnProperty('x') //true 判断x是否为self1实力对象的自身属性
        self1.hasOwnProperty('y') //true
        self1.hasOwnProperty('toString') //false
        self1.__proto__.hasOwnProperty('toString') //true toString方法属于其原型链上的方法
        obj instanceof Self //判断obj是否为self对象的实例

> 静态方法
> 父类的静态方法可以被子类继承,但不会被实例继承

        class Foo{
            static classMethod(){
                return 'hello';
                this.propMethod(); //this指向的是类Foo,而不是实例
            }
            propMethod(){
                console.log('hello')
            }
        }

        Foo.classMethod() //'hello' ,静态方法可以直接在Foo类上调用;其他的方法是定义在原型上不能直接调用
        Foo.propMethod() //typeError

* 实例函数 不能继承静态方法

        var foo = new Foo();
        foo.classMethod() //typeError 静态方法不能被实例继承
        foo.propMethod(); //hello

* 子类 可以调用父类的静态方法

        class Bar extends Foo{
            static classMethod(){
                return super.classMethod() + ',too'
            }
        }
        Ber.classMethod() //hello,too


> 私有属性和私有方法新提案

        class Foo {
            #a;
            #b;
            constructor(a, b) {
            this.#a = a;
            this.#b = b;
            }
            #sum() {
            return #a + #b;
            }
            printSum() {
            console.log(this.#sum());
            }
        }


async

>async的实现原理:就是将 Generator函数和自动执行器,包装在一个函数里

        async function myFunction() {
            try {
            await somethingThatReturnsAPromise();
            } catch (err) {
            console.log(err);
            }
        }

* 优点:1 内置执行器。2 更好的语义。3.返回Promise。

* 注意点:
    * 1. await命令后面的Promise对象,运行结果可能是rejected,所以最好把await命令放在try...catch代码块中。
    * 2.多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。

            let foo = await getFoo();
            let bar = await getBar();
            // 改写成
            let fooPromise = getFoo();
            let barPromise = getBar();
            let foo = await fooPromise;
            let bar = await barPromise;
posted @ 2019-04-13 10:50  筱qian  阅读(383)  评论(0编辑  收藏  举报