在看js编程风格的时候,遇到了一个比较常见的问题:
使用 Array#slice 将类数组对象转换成数组。
function trigger() {
var args = Array.prototype.slice.call(arguments);
...
}
恰巧早些在某个大神的面试经历中看到这题,将arguments转换为数组。但是,背后的原理是怎样的,却一直没有时间去探究一下。为什么类数组对象可以转换成数组?
不知道大家有没有想过。
早些时候在javascript秘密花园
一书中分析的一个比较麻烦的apply和call连用代码,
以为道理是一样的,但是好像并没有。
回答:是的!
主要看其实现的步骤中的Repeat
一步,那是不是说无论是数组还是类数组对象,其实都是根据Pk
这个非负整数字符串(数组下标)来作为对象的属性获取相应的值(数组也算是对象),而类数组对象的属性和数组的属性很接近,除了_proyo_
属性。【update.PS:根据目前的有限水平和字面意思,以及输出数组和类数组对象进行验证,难免有错误,欢迎指(da)出(lian):)】
最后一段:
NOTE: The slice function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be transferred to other kinds of objects for use as a method. Whether the slice function can be applied successfully to a host object is implementation-dependent.
能不能将对象成功地转换为数组,依赖于实现。个人的理解,这里的意思是,这个对象需要符合一些特征(也就是类数组对象)。
类数组对象的定义如下:
-
拥有length属性,其它属性(索引)为非负整数(对象中的索引会被当做字符串来处理,这里你可以当做是个非负整数串来理解)
-
不具有数组所具有的方法
下面利用代码来验证是不是,存在多种情况,但是为了编程上的数据问题,最好是对象的key从"0"开始,且都为非负整数对应的字符串,而且length属性对应数组长度。
//以下代码在chrome浏览器运行通过
//情况1,无length属性,但属性为非负整数--输出空数组
let result = [].slice.call({"0":"first","1":"second"});
console.log(result);
//[]
//情况2,无length属性,属性不为非负整数--输出空数组
let result = [].slice.call({"a":"first","b":"second"});
console.log(result);
//[]
//情况3,有length属性,但属性不为非负整数--输出长度为length,值都为undefined的数组
let result = [].slice.call({"a":"first","b":"second",length:2});
console.log(result);
//[ , ]
//情况4,有length属性,属性存在有非负整数--输出长度为length,下标的值为对应key的value
let result = [].slice.call({"a":"b","0":"first","5":"second",length:6});
console.log(result);
//["first", , , ,"second", ]
参考链接: