zoukankan      html  css  js  c++  java
  • [Effective JavaScript 笔记]第51条:在类数组对象上复用通用的数组方法

    前面有几条都讲过关于Array.prototype的标准方法。这些标准方法被设计成其他对象可复用的方法,即使这些对象并没有继承Array。

    arguments对象

    在22条中提到的函数arguments对象。它是一个类数组对象,并不是一个标准的数组,所以无法使用数组原型中的方法,因此无法使用arguments.forEach这样的形式来遍历每一个参数。这里我们必须使用call方法来对使用forEach方法。

    function highlight(){
      [].forEach.call(arguments,function(widget){
         widget.setBackground('yellow');
      });
    }
    

    forEach是一个函数对象,所以它继承了Function.prototype对象中的call方法。这里就可以使用一个指定的对象作为函数内部this的绑定对象来调用它,并紧随任意数量的参数。
    ## NodeList对象
    在Web平台,DOM的NodeList类是另一个类数组对象。类似的document.getElementsByTagName会返回一个NodeList类数组对象。这个对象也没有继承自Array.prototype.

    类数组对象

    怎样构建一个类数组对象?

    • 具有一个范围在0到2^32-1的整形length属性

    • length属性大于该对象的最大索引。索引是一个范围在0到2^32-1的整数,它的字符串表示是该对象中的一个key

    实现上面这两点,就可以使一个对象与Array.prototype中任一方法兼容。
    一个简单的对象字面量也可以用来创建一个类数组对象。

    var arrayLike={0:'a',1:'b',2:'c',length:3};
    var res=Array.prototype.map.call(arrayLike,function(s){
        return s.toUpperCase();
    });
    res;//['A','B','C']

    字符串

    也是可以表现为数组,因为它们是可索引,并且其长度也可以通过length属性获取。
    因此,Array.protoype中的方法操作字符串时并不会修改原始字符串。

    var res=Array.prototype.map.call('abc',function(s){return s.toUpperCase();});
    res;//['A','B','C']

    模拟数组

    模拟数组的所有行为,归功于数组行为的两方面:

      • 将length属性值设为小于n的值会自动地删除索引值大于或等于n的所有属性

      • 增加一个索引值为n(大于或等于length属性值)的属性会自动地设置length属性为n+1

    其中第2条规则不好实现,因为需要监控索引属性的增加以自动地更新length属性。

    对于Array.prototype中的方法,这两条都不是必须的,因为在增加或删除索引属性的时候它们都会强制地更新length属性。
    Array方法中只有一个不是通用的,即数组连接方法concat。该方法可以由任意的类数组接收者调用,但它会检查其参数[[Class]]属性。如果参数是一个真实的数组,那么concat会将该数组的内容连接起来作为结果;否则,参数将以一个单一的元素来连接。
    例如,不能简单地连接一个以arguments对象作为内容的数组。

    function namesColumn(){
      return ['Names'].concat(arguments);
    }
    namesColumn('张三','李四','王五');//["Names", Arguments[3]0: "张三"1: "李四"2: "王五"callee: namesColumn()length: 3Symbol(Symbol.iterator): values()__proto__: Object]

    使concat方法将一个类数组对象视为真实数组,需要把类数组转换为真正的数组。使用slice对类数组对象进行转换。

    function namesColumn(){
      return ['Names'].concat([].slice.call(arguments));
    }
    namesColumn('张三','李四','王五');//["Names", "张三", "李四", "王五"]

    提示

    • 对于类数组对象,通过提取方法对象并使用其call方法来复用通用的Array方法

    • 任意一个具有索引属性和恰当length属性的对象都可以使用通用的Array方法

  • 相关阅读:
    生成格雷码 转自leetcode
    webstorm注册码 永久有效!!!(亲测有效)
    Myeclipse或者eclipse太卡
    对封装的再次理解(容器)
    几个好的参考的网站
    将json字符串转为json对象,从对象中取需要的数据
    ElementUI学习笔记
    Oracle的case when 和decode
    20190807更新数据相关笔记
    oracle未查找到任何数据问题
  • 原文地址:https://www.cnblogs.com/wengxuesong/p/5626364.html
Copyright © 2011-2022 走看看