在类数组对象上复用通用的数组方法

前面有几条都讲过关于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.

类数组对象:

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

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

2.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']
模拟数组:

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

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

2.增加一个索引值为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", "张三", "李四", "王五"]
总结:

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

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





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值