美文网首页Web前端之路
ECMAScript 6 备忘录

ECMAScript 6 备忘录

作者: 路漫漫在狂奔 | 来源:发表于2017-05-25 10:46 被阅读41次

    本文摘自刘哇勇的部落格,加入一些自己的吐槽和小修改

    箭头操作符

    这里箭头函数除了简洁,干掉function特性外,还有个非常重要的功能:那就是this问题!
    js面向对象写法用的多的人坑定遇到过坑爹的问题就是this居然不是指向调用者,所以在很多框架里我们常常看到这么句code :var self = this;

    let array = ['a', 'b', 'c'];
    //传统写法
    array.forEach(function(v, i, a) {
        console.log(v,i,a);
    });
    //ES6 加{} 表示无返回   不加{}  表示 return ;
    array.forEach((v, i, a) => console.log(v,i,a));//相当于  => { return console.log(v,i,a); } 
    array.forEach((v, i, a) => {console.log(v,i,a);});
    
    //进阶
    function Player() {
      var self = this; 
      self.hp= 0;
      setInterval(function () {
        // 回调里面的 `self` 变量就指向了期望的那个对象了
        self.hp++;
      }, 1000);
    }
    // ES6
    class Player{
        constructor() {
            this.hp= 0;
            setInterval(() => {
                  this.hp++; // this正确地指向了Player对象
             }, 1000);
        }
    }
    var p = new Player();
    

    字符串模板

    let str = 'test';
    //后端的同学有没有发现 "your num is $str".......
    console.log(`your num is ${str}`);
    

    默认参数值

    我现在都记得当我第一次在js里写下function(a='test'){} 然后居然竟然报错时的表情!!! NOW,I AM RIGHT!

    function sayHello(name){
        //传统的指定默认参数的方式
        var name=name||'dude';
        console.log('Hello '+name);
    }
    //运用ES6的默认参数
    function sayHello2(name='dude'){
        console.log(`Hello ${name}`);
    }
    sayHello();//输出:Hello dude
    sayHello('Wayou');//输出:Hello Wayou
    sayHello2();//输出:Hello dude
    sayHello2('Wayou');//输出:Hello Wayou
    

    类的支持

    作为一个后端,看到字符串模板和这个特性,我简直激动的说不出话来

    //类的定义
    class PHPClass {
        //ES6构造函数
        constructor(name) {
            this.name = name;
        }
        showName() {
            console.log(`我是${this.name}`);
        }
    }
    //类的继承
    class JSClass extends PHPClass {
        constructor(name) {
            //调用父类构造器
            super(name);
        }
    }
    
    let php = new PHPClass('php'),
    js = new JSClass('js');
    php.showName();//'我是php'
    js.showName();//'我是js'
    

    增强的对象字面量

    //通过对象字面量创建对象
    let human = {
        breathe() {
            console.log('breathing...');
        }
    };
    let worker = {
        __proto__: human, //设置此对象的原型为human,相当于继承human
        company: 'freelancer',
        work() {
            console.log('working...');
        }
    };
    human.breathe();//输出 ‘breathing...’
    //调用继承来的breathe方法
    worker.breathe();//输出 ‘breathing...’
    

    解构

    let [x,y]=getVal(),//函数返回值的解构
        [name,,age]=['wayou','male','secrect'];//数组解构
    
    function getVal() {
        return [ 1, 2 ];
    }
    
    console.log('x:'+x+', y:'+y);//输出:x:1, y:2 
    console.log('name:'+name+', age:'+age);//输出: name:wayou, age:secrect
    

    不定参数

    //将所有参数相加的函数
    function add(...x){
        return x.reduce((m,n)=>m+n);
    }
    //传递任意个数的参数
    console.log(add(1,2,3));//输出:6
    console.log(add(1,2,3,4,5));//输出:15
    

    拓展参数

    var people=['Wayou','John','Sherlock'];
    //sayHello函数本来接收三个单独的参数人妖,人二和人三
    function sayHello(people1,people2,people3){
        console.log(`Hello ${people1},${people2},${people3}`);
    }
    //但是我们将一个数组以拓展参数的形式传递,它能很好地映射到每个单独的参数
    sayHello(...people);//输出:Hello Wayou,John,Sherlock 
    
    //而在以前,如果需要传递数组当参数,我们需要使用函数的apply方法
    sayHello.apply(null,people);//输出:Hello Wayou,John,Sherlock 
    

    let与const 关键字

    for (let i=0;i<2;i++)console.log(i);//输出: 0,1
    console.log(i);//输出:undefined,严格模式下会报错
    
    const ROOT = '/';
    ROOT = './';//报错
    

    for of 值遍历

    let someArray = [ "a", "b", "c" ];
    for (v in someArray) {
        console.log(v);//输出 0,1,2
    }
    for (v of someArray) {
        console.log(v);//输出 a,b,c
    }
    

    以下为完全ctrl + c, ctrl + v.工作里暂时用不到,脑容量有限,放到这以后查阅用


    iterator, generator

    这一部分的内容有点生涩,详情可以参见这里。以下是些基本概念。

    iterator:它是这么一个对象,拥有一个next方法,这个方法返回一个对象{done,value},这个对象包含两个属性,一个布尔类型的done和包含任意值的value
    iterable:这是这么一个对象,拥有一个obj[@@iterator]方法,这个方法返回一个iterator
    generator:它是一种特殊的iterator。反的next方法可以接收一个参数并且返回值取决与它的构造函数(generator function)。generator同时拥有一个throw方法
    generator 函数: 即generator的构造函数。此函数内可以使用yield关键字。在yield出现的地方可以通过generator的next或throw方法向外界传递值。generator 函数是通过function*来声明的
    yield 关键字:它可以暂停函数的执行,随后可以再进进入函数继续执行
    模块

    在ES6标准中,JavaScript原生支持module了。这种将JS代码分割成不同功能的小块进行模块化的概念是在一些三方规范中流行起来的,比如CommonJS和AMD模式。

    将不同功能的代码分别写在不同文件中,各模块只需导出公共接口部分,然后通过模块的导入的方式可以在其他地方使用。下面的例子来自tutsplus:

    // point.js
    module "point" {
        export class Point {
            constructor (x, y) {
                public x = x;
                public y = y;
            }
        }
    }
     
    // myapp.js
    //声明引用的模块
    module point from "/point.js";
    //这里可以看出,尽管声明了引用的模块,还是可以通过指定需要的部分进行导入
    import Point from "point";
     
    var origin = new Point(0, 0);
    console.log(origin);
    
    

    Map,Set 和 WeakMap,WeakSet

    这些是新加的集合类型,提供了更加方便的获取属性值的方法,不用像以前一样用hasOwnProperty来检查某个属性是属于原型链上的呢还是当前对象的。同时,在进行属性值添加与获取时有专门的get,set 方法。

    下方代码来自es6feature

    // Sets
    var s = new Set();
    s.add("hello").add("goodbye").add("hello");
    s.size === 2;
    s.has("hello") === true;
    
    // Maps
    var m = new Map();
    m.set("hello", 42);
    m.set(s, 34);
    m.get(s) == 34;
    

    有时候我们会把对象作为一个对象的键用来存放属性值,普通集合类型比如简单对象会阻止垃圾回收器对这些作为属性键存在的对象的回收,有造成内存泄漏的危险。而WeakMap,WeakSet则更加安全些,这些作为属性键的对象如果没有别的变量在引用它们,则会被回收释放掉,具体还看下面的例子。

    正文代码来自es6feature

    // Weak Maps
    var wm = new WeakMap();
    wm.set(s, { extra: 42 });
    wm.size === undefined
    
    // Weak Sets
    var ws = new WeakSet();
    ws.add({ data: 42 });//因为添加到ws的这个临时对象没有其他变量引用它,所以ws不会保存它的值,也就是说这次添加其实没有意思
    

    Proxies

    Proxy可以监听对象身上发生了什么事情,并在这些事情发生后执行一些相应的操作。一下子让我们对一个对象有了很强的追踪能力,同时在数据绑定方面也很有用处。

    以下例子借用自这里。

    //定义被侦听的目标对象
    var engineer = { name: 'Joe Sixpack', salary: 50 };
    //定义处理程序
    var interceptor = {
      set: function (receiver, property, value) {
        console.log(property, 'is changed to', value);
        receiver[property] = value;
      }
    };
    //创建代理以进行侦听
    engineer = Proxy(engineer, interceptor);
    //做一些改动来触发代理
    engineer.salary = 60;//控制台输出:salary is changed to 60
    

    上面代码我已加了注释,这里进一步解释。对于处理程序,是在被侦听的对象身上发生了相应事件之后,处理程序里面的方法就会被调用,上面例子中我们设置了set的处理函数,表明,如果我们侦听的对象的属性被更改,也就是被set了,那这个处理程序就会被调用,同时通过参数能够得知是哪个属性被更改,更改为了什么值。

    Symbols

    我们知道对象其实是键值对的集合,而键通常来说是字符串。而现在除了字符串外,我们还可以用symbol这种值来做为对象的键。Symbol是一种基本类型,像数字,字符串还有布尔一样,它不是一个对象。Symbol 通过调用symbol函数产生,它接收一个可选的名字参数,该函数返回的symbol是唯一的。之后就可以用这个返回值做为对象的键了。Symbol还可以用来创建私有属性,外部无法直接访问由symbol做为键的属性值。
    以下例子来自es6features

    (function() {
    
      // 创建symbol
      var key = Symbol("key");
    
      function MyClass(privateData) {
        this[key] = privateData;
      }
    
      MyClass.prototype = {
        doStuff: function() {
          ... this[key] ...
        }
      };
    
    })();
    
    var c = new MyClass("hello")
    c["key"] === undefined//无法访问该属性,因为是私有的
    

    Math,Number,String,Object 的新API

    对Math,Number,String还有Object等添加了许多新的API。下面代码同样来自es6features,对这些新API进行了简单展示。

    Number.EPSILON
    Number.isInteger(Infinity) // false
    Number.isNaN("NaN") // false
    
    Math.acosh(3) // 1.762747174039086
    Math.hypot(3, 4) // 5
    Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2
    
    "abcde".contains("cd") // true
    "abc".repeat(3) // "abcabcabc"
    
    Array.from(document.querySelectorAll('*')) // Returns a real Array
    Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior
    [0, 0, 0].fill(7, 1) // [0,7,7]
    [1,2,3].findIndex(x => x == 2) // 1
    ["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"]
    ["a", "b", "c"].keys() // iterator 0, 1, 2
    ["a", "b", "c"].values() // iterator "a", "b", "c"
    
    Object.assign(Point, { origin: new Point(0,0) })
    

    Promises

    Promises是处理异步操作的一种模式,之前在很多三方库中有实现,比如jQuery的deferred 对象。当你发起一个异步请求,并绑定了.when(), .done()等事件处理程序时,其实就是在应用promise模式。

    //创建promise
    var promise = new Promise(function(resolve, reject) {
        // 进行一些异步或耗时操作
        if ( /*如果成功 */ ) {
            resolve("Stuff worked!");
        } else {
            reject(Error("It broke"));
        }
    });
    //绑定处理程序
    promise.then(function(result) {
        //promise成功的话会执行这里
        console.log(result); // "Stuff worked!"
    }, function(err) {
        //promise失败会执行这里
        console.log(err); // Error: "It broke"
    });
    

    总结

    总结就是一句话,前后端差异越来越小了。幸福了谁?哭了谁?

    REFERENCE

    Google traceur online compiler http://google.github.io/traceur-compiler/demo/repl.html
    array destruction http://ariya.ofilabs.com/2013/02/es6-and-destructuring-assignment.html
    class http://www.joezimjs.com/javascript/javascript-prototypal-inheritance-and-what-es6-classes-have-to-say-about-it/
    enhanced object literal http://maximilianhoffmann.com/posts/object-based-javascript-in-es6
    parameters http://globaldev.co.uk/2013/10/es6-part-4/
    let keyword http://globaldev.co.uk/2013/09/es6-part-2/
    for of iterator https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of#Browser_compatibility
    the Iterator protocol https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/The_Iterator_protocol
    generators https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
    ES6 Iterators, Generators, and Iterables http://domenic.me/2013/09/06/es6-iterators-generators-and-iterables/
    proxies http://ariya.ofilabs.com/2013/07/es6-and-proxy.html
    symbols http://tc39wiki.calculist.org/es6/symbols/
    promise http://www.html5rocks.com/en/tutorials/es6/promises/

    相关文章

      网友评论

        本文标题:ECMAScript 6 备忘录

        本文链接:https://www.haomeiwen.com/subject/agiaxxtx.html