Skip to content

Instantly share code, notes, and snippets.

@GeekaholicLin
Last active December 6, 2016 13:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GeekaholicLin/a54c1ff966c04cc4320a2cc9d47693f8 to your computer and use it in GitHub Desktop.
Save GeekaholicLin/a54c1ff966c04cc4320a2cc9d47693f8 to your computer and use it in GitHub Desktop.
如何将arguments转换为参数数组--javascript

问题的由来

在看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", ]

参考链接:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment