You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
functionfn(){// Uncaught TypeError: arguments.push is not a function// arguments.push(4);vararr=[];for(vari=0,len=arguments.length;i<len;i++)arr[i]=arguments[i];arr.push(4);// [1, 2, 3, 4]}fn(1,2,3);
小结下,如果要把 Array-Like Objects 转为 Array,首选 Array.prototype.slice,但是由于 IE 下 Array.prototype.slice.call(nodes) 会抛出错误(because a DOM NodeList is not a JavaScript object),所以兼容的写法如下。(但还有一点要注意的是,如果是 arguments 转为 Array,最好别用 Array.prototype.slice,V8 下会很慢,具体可以看下 避免修改和传递 arguments 给其他方法 — 影响优化 )
functionnodeListToArray(nodes){vararr,length;try{// works in every browser except IEarr=[].slice.call(nodes);returnarr;}catch(err){// slower, but works in IEarr=[];length=nodes.length;for(vari=0;i<length;i++){arr.push(nodes[i]);}returnarr;}}
这篇文章拖了有两周,今天来跟大家聊聊 JavaScript 中一类特殊的对象 -> Array-Like Objects。
Array-Like
JavaScript 中一切皆为对象,那么什么是 Array-Like Objects?顾名思义,就是像数组的对象,当然,数组本身就是对象嘛!稍微有点基础的同学,一定知道 arguments 就是 Array-Like Objects 的一种,能像数组一样用
[]
去访问 arguments 的元素,有length
属性,但是却不能用一些数组的方法,如 push,pop,等等。那么,什么样的元素是 Array-Like Objects?我们来看看 underscore 中对其的定义。
很简单,不是数组,但是有
length
属性,且属性值为非负 Number 类型即可。至于length
属性的值,underscore 给出了一个上限值 MAX_ARRAY_INDEX,其实是 MAX_SAFE_INTEGER(感谢 @HangYang 同学指出) ,因为这是 JavaScript 中能精确表示的最大数字。(数组最大长度应该为 Math.pow(2,32) - 1)想想还有什么同时能满足以上条件的?NodeList,HTML Collections,仔细想想,甚至还有字符串,或者拥有
length
属性的对象,函数(length 属性值为形参数量),等等。Array-Like to Array
有的时候,需要将 Array-Like Objects 转为 Array 类型,使之能用数组的一些方法,一个非常简单粗暴并且兼容性良好的方法是新建个数组,然后循环存入数据。
我们以 arguments 为例。
但是这不是最优雅的,更优雅的解法大家一定都知道了,use Array.prototype.slice(IE9- 会有问题)。
或者可以用
[]
代替 Array.prototype 节省几个字节。如果非得追求性能,用
[]
会新建个数组,性能肯定不及前者,但是由于引擎的优化,这点差异基本可以忽略不计了(所以很多框架用的就是后者)。为什么这样可以转换?我们简单了解下,主要的原因是 slice 方法只需要参数有 length 属性即可。首先,slice 方法得到的结果是一个 新的数组,通过 Array.prototype.slice.call 传入的参数(假设为 a),如果没有 length 属性,或者 length 属性值不是 Number 类型,或者为负,那么直接返回一个空数组,否则返回 a[0]-a[length-1] 组成的数组。(具体可以看下 v8 源码 https://github.com/v8/v8/blob/master/src/js/array.js#L621-L660)
当然,ES6 提供了更简便的方法。
小结下,如果要把 Array-Like Objects 转为 Array,首选 Array.prototype.slice,但是由于 IE 下 Array.prototype.slice.call(nodes) 会抛出错误(because a DOM NodeList is not a JavaScript object),所以兼容的写法如下。(但还有一点要注意的是,如果是 arguments 转为 Array,最好别用 Array.prototype.slice,V8 下会很慢,具体可以看下 避免修改和传递 arguments 给其他方法 — 影响优化 )
Others
很多时候,某个方法你以为接收的参数是数组,其实类数组也是可以的。
Function.prototype.apply() 函数接收的第二个参数,其实也可以是类数组。
Read More
The text was updated successfully, but these errors were encountered: