JS 中的arguments转化为数组:
网上都是这样写的:Array.prototype.slice.call(arguments,0)
或者是: [].slice.call(arguments,0);
不是特别理解这样的写法,原理是什么?
请各位大神赐教~~~~
首先你要理解call。 其实就是将arguments当做this传递给Array的原型方法slice。
w3c 官方给出的解释是 call:call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。感觉比较抽象,能不能详细的用白话 解释下??
还有一个疑问,关于slice,我是不是可以这样理解,slice也是一个function,任何function都有call方法,所以可以这样用?
@天空的天: slice是Array.prototype上的方法,因为call是Function的原型方法,所以function都可以使用。一般写原型方法就是Array.prototype.xxx = function(){this.aaa='xxx';},可以使用this。call的作用就是将第一个参数传递进去,方法里的this就是第一个参数。
1.
arguments只是一个类似数组的对象,但并不是Array的实例。arguments可以通过arguments[0],arguments[1].....来访问传入参数,可以通过arguments.length获取传入参数的个数。(《Javascript高级程序设计(第3版)》3.7.1理解参数)
2.
再看看slice() 方法,这里说slice方法是Array对象的方法。
3.
call方法是函数的一个方法,可以用来调用自己,例如定义了一个sayHello方法:
function add(num1, num2){ return num1+num2; }
可以这样调用add.call(this, 1, 2),那么返回的就是3,
但是第一个参数是可以改变函数的作用域的(这个三言两语也说不清楚,贴一个链接吧,Javascript中call的使用)
所以,arguments直接调用slice是不可以的,因为它不是真的Array对象。至于为什么可以通过Array.prototype.slice.call(arguments, 0)来调用,我只能推测了,推测slice也是可以对类数组进行切割的,而且返回的就是一个Array对象,而被作用的对象就是call方法内部的this,这里通过传入arguments改变了call内部的作用域的this对象,而刚好arguments是可以用过索引取值的,而且有length属性来获取长度。
可以认为arguments有点像C#里的实现了IEnumerable接口,但是不是Array。
说了半天,我其实也只是推测的一个结论,没找到权威资料说明这个问题,希望可以帮助你理解。
@天空的天: 不知道你有没有考虑过为什么arguments需要转换才能变成数组?arguments其实本身已经具备了数组的一些行为,我其实是在尝试说明这个问题。