读深入ES6记[一]

作者: 蛋先生DX | 来源:发表于2016-07-22 12:19 被阅读240次
    ES6

    划重点了,有没像期末考时老师给题目范围的感觉,呵呵。

    该笔记系列主要是在阅读深入ES6系列文章时,自己印象较为深刻的部分的记录,也是自己对学习内容的一些总结,目的在于当自己有点忘却的时候,可以快速看看自己这里所写内容就可以记起大概。当然,如果正在阅读本篇文章的你们,可以通过该文章对ES6有个快速简单的了解,那就太太好了。闲话不多说,开始写写写。。。

    第一章:ES6介绍

    1.ECMAScript是一个程序语言标准,它描述了这门语言的语法,类型,标准库等。

    2.Javascript是它的实现和扩展(微软的Jscript也是其实现和扩展)。

    3.ES6就是指ECMAScript这个标准的第6版

    4.文中提到ES5中引入了一些新特性,其中Object.create()让我较感兴趣,跟对象的继承实现有关系,我们看下MDN对该方法的描述:

    The Object.create() method creates a new object with the specified prototype object and properties.

    即通过指定原型object和属性来创建新的object,怎么用在继承实现上,代码伺候:

    function Super() {
      this.name = 'super';
    }
    Super.prototype.sayName = function () {
      console.log(this.name);
    }
    
    function Sub() {
      Super.call(this);
    }
    // Sub.prototype = new Super(); // 用new的方式继承原型
    Sub.prototype = Object.create(Super.prototype); // 用Object.create的方式继承原型
    Sub.prototype.constructor = Sub;
    
    

    Object.create()更优,因为这样的写法来继承prototype更直观易懂,而且子类的prototype不会包含多余的父类属性(如例子中的name)

    有没同学会问用new的方式,子类的prototype会包含父类的属性,那这个属性会不会造成影响?
    答案是不会滴,因为我们在子类的构造函数中调用了Super.call(this)来达到每个子类的实例都拥有自己的一份属性(name),而作用域是先从实例来查看该属性是否存在,不存在才去prototype查找。很明显实例中存在,所以子类中的prototype的属性其实没什么用

    第二章:迭代器(Iterator)与for-of循环

    1.避免for-in来遍历数组,因为它是一个坑,为啥?

    坑 1

    var arr = ['foo', 'bar'];
    for (var idx in arr) {
      console.log(arr[idx]);
    }
    

    idx是字符串,如果你把它当数字,进行了类似这样的计算idx + 1就悲剧了,因为它的值会像这样"01","11"。
    为啥它是字符串而不是数字呢?因为人家本来就设计来遍历对象的嘛,对象的key一般都是字符串嘛

    坑 2

    var arr= ['a', 'b'];
    arr.key = 'value';
    for (var idx in arr) {
      console.log(idx); // 输出"0" "1" "key"
    }
    

    for-in会遍历对象的所有可枚举的属性,包括自定义和原型中的属性,所以有些行为可能不如你所愿

    2.for-of遍历数组数据的理想作法

    为啥理想呢?因为它没有for-in的坑,把上面for-in的代码用for-of试一下就清楚了
    还有循环中我们总是希望在某些条件下跳过或者打断循环,在for-of里面是可以通过breakcontinuereturn控制循环

    3.哪些数据类型可以使用for-of

    实现了迭代器接口方法([Symbol.iterator]()和next())的对象都可以使用。
    内建的Array,Map,Set等自实现了迭代器接口,所以可以使用for-of
    普通对象Object是不能使用for-of的,因为,来,你说一下,哈。试下这里的代码,看会报什么错:for (var val of {a: 1}) {}

    4.让普通对象Object也能for-of

    上面提到需要实现迭代器接口才能使用for-of来遍历数据,那我们来看看怎么让普通对象Object也能拥有此特性
    注意:以下仅用于举例说明,如想用于生产环境,风险自负哈

    Object.prototype[Symbol.iterator] = function() {
      return this; // 返回迭代器对象。一个迭代器必须实现了next接口,返回值格式为{done: [bool], value: }
    };
    Object.prototype.next = function () {
      this.currentIdx = (this.currentIdx === undefined ? -1 : this.currentIdx) + 1;
      let keys = Object.keys(this);
      let keyTotal = keys.length - 1; // 排除掉currentIdx这个属性
      let done = keyTotal < this.currentIdx + 1;
      let key = done ? null : keys[this.currentIdx];
      let value = key ? this[key] : undefined;
      return {done: done, value: value};
    };
    
    obj = {a: 1};
    for (let val of obj) {
      console.log(val);
    }
    

    5.Why [Symbol.iterator]?代码不好看有木有

    有没人有疑问,为啥要用[Symbol.iterator],这看上去不太优雅呀,改成iterator多好,比如Object.prototype.iterator = function() {}
    制定标准的人还是考虑得很周到的,万一别人的对象已经有iterator方法呢?所以为了不造成冲突,用Symbol是个好做法(Symbol是什么东东,后面会讲到,不懂的先带着疑问看下去吧)

    6.为啥用迭代器设计模式?不就遍历数据而已吗?

    有思考过这个问题的人举个手呗(好吧,反正我看不到)。
    有没人说数组用自己的遍历方式,Map用自己的遍历方式等就行拉。当然,可以,但只能说思想境界不同而已。
    迭代器设计模式的引入是为了让调用者可以不关心数据的存储细节(Array?Map?Set?or other...),用统一的接口(比如Javascript这里用for-of)来遍历数据,而要实现遍历的对象也只需实现迭代器规定的接口即可。
    常见的迭代器的接口设计有:
    以Java为代表:hasNext和next方法
    以Python为代表:只有next方法,无值时抛异常
    以Javascript为代表:只有next方法,返回对象中用done属性来表明是否遍历完成

    7.用简单等价代码理解for-of

    我们以上面实现了迭代器的普通对象来继续这个话题

    var obj = {a: 1};
    
    for (let val of obj) {
      console.log(val);
    }
    

    从以下简单等价的代码可看出for-of的基本逻辑,当然,实际的for-of实现会更复杂些

    var obj = {a: 1};
    
    var iterator = obj[Symbol.iterator]();
    var result = iterator.next();
    while(!result.done) {
      var value = result.value;
    
      // 一些语句
      console.log(value);
    
      result = iterator.next();
    }
    

    这就是第一,二章的学习情况,接下来可继续看《读深入ES6记[二]》

    --EOF--

    相关文章

      网友评论

        本文标题:读深入ES6记[一]

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