在类数组对象上复用通用的数组方法
2017-08-20 22:37
246 查看
前面有几条都讲过关于Array.prototype的标准方法。这些标准方法被设计成其他对象可复用的方法,即使这些对象并没有继承Array。
arguments对象:
在22条中提到的函数arguments对象。它是一个类数组对象,并不是一个标准的数组,所以无法使用数组原型中的方法,因此无法使用arguments.forEach这样的形式来遍历每一个参数。这里我们必须使用call方法来对使用forEach方法。
NodeList对象
在Web平台,DOM的NodeList类是另一个类数组对象。类似的document.getElementsByTagName会返回一个NodeList类数组对象。这个对象也没有继承自Array.prototype.
类数组对象:
怎样构建一个类数组对象?
1.具有一个范围在0到2^32-1的整形length属性
2.length属性大于该对象的最大索引。索引是一个范围在0到2^32-1的整数,它的字符串表示是该对象中的一个key
实现上面这两点,就可以使一个对象与Array.prototype中任一方法兼容。
一个简单的对象字面量也可以用来创建一个类数组对象。
也是可以表现为数组,因为它们是可索引,并且其长度也可以通过length属性获取。
因此,Array.protoype中的方法操作字符串时并不会修改原始字符串。
模拟数组的所有行为,归功于数组行为的两方面:
1.将length属性值设为小于n的值会自动地删除索引值大于或等于n的所有属性
2.增加一个索引值为n(大于或等于length属性值)的属性会自动地设置length属性为n+1
其中第2条规则不好实现,因为需要监控索引属性的增加以自动地更新length属性。
对于Array.prototype中的方法,这两条都不是必须的,因为在增加或删除索引属性的时候它们都会强制地更新length属性。
Array方法中只有一个不是通用的,即数组连接方法concat。该方法可以由任意的类数组接收者调用,但它会检查其参数[[Class]]属性。如果参数是一个真实的数组,那么concat会将该数组的内容连接起来作为结果;否则,参数将以一个单一的元素来连接。
例如,不能简单地连接一个以arguments对象作为内容的数组。
总结:
1.对于类数组对象,通过提取方法对象并使用其call方法来复用通用的Array方法
2.任意一个具有索引属性和恰当length属性的对象都可以使用通用的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对类数组对象进行转换。
总结:
1.对于类数组对象,通过提取方法对象并使用其call方法来复用通用的Array方法
2.任意一个具有索引属性和恰当length属性的对象都可以使用通用的Array方法
相关文章推荐
- [Effective JavaScript 笔记]第51条:在类数组对象上复用通用的数组方法
- json对象与数组以及转换成js对象的方法
- Effective Java系列读后感(二)-对于所有对象都通用的方法
- Java获取json数组对象的方法
- [Effective Java]第三章 对所有对象都通用的方法
- C++ 与“类”有关的注意事项总结(十):类对象数组初始化(三种方法)
- js中数组对象去重的方法
- javascript 数组对象中的迭代方法
- 对于所有方法都通用的对象
- JavaScript字符串对象split方法入门实例(用于把字符串分割成数组)
- oracle 存储过程返回对象数组的方法
- 给Array本地对象增加一个原型方法,他的用途是删除数组中重复的条目,并将新的数组返回
- PHP实现删除多重数组对象属性并重新赋值的方法
- js中那些方法不改变原来的数组对象
- 10-10 arguments存储实参、解决js获取CSS属性值兼容性、object对象、for语句遍历对象内容、数组中的方法
- 优雅编程之这样使用对象通用方法,你就“正常”了(三十四)
- java在list集合指定位置插入对象和js在数组指定位置插入对象的方法
- 抽象公共类,复用公共方法为多个对象
- List对象排序通用方法
- JS遍历数组和对象的区别及递归遍历对象、数组、属性的方法详解