先放结论:[].slice.call(arguments)
能将具有length
属性的对象转成数组。
1、基础知识
-
.slice()
方法-
定义和用法
slice(start, end)
方法可提取数组的某个部分,并以新的数组返回被提取的部分。
使用start
(包含) 和end
(不包含) 参数来指定提取数组开始和结束的部分。- 如果未指定start和end,则返回整个数组。
- 如果指指定一个参数,该参数作为start使用,返回包括start位置之后的全部数组。
- 如果是负数,则该参数规定的是从数组的尾部开始算起的位置。也就是说,-1 指数组的最后一项,-2 指倒数第二个项,以此类推。
实例
-
//在数组中读取元素:
var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
var citrus = fruits.slice(-3,-1);
citrus 结果输出:
["Lemon", "Apple"]
-
.call()
方法- 定义和用法
call()
函数用于调用当前函数functionObject
,并可同时使用指定对象thisObj
作为本次执行时functionObject
函数内部的this
指针引用。 - 实例
- 定义和用法
var obj = {name: "李四", age: 20};
function foo(a, b){
document.writeln(this.name);
document.writeln(a);
document.writeln(b);
}
// 改变this引用为obj,同时传递两个参数
foo.call(obj, 12, true); // 李四 12 true
2.进入正题
当我看到var args = [].slice.call(arguments, 0);
这种写法的时候是一脸懵逼的(黑人问号脸)。
arguments
是一个对象而不是数组,最多算是一个伪数组,而且自身的原型链上也没有slice
这个方法。
/*确定arguments的类型
* 返回 3,Object, true;
*/
(function(a,b,c){
console.log(arguments.length);
console.log(typeof arguments);
console.log( arguments instanceof Object);
}(1,2,3))
[].slice.call(arguments)
能将具有length
属性的对象转成数组:
-
[]
自身也是也是一个对象.而数组原型链上有这个slice
这个方法。
/*此处的返回值是true*/
[].slice === Array.prototype.slice;
- 通过
call
显式绑定来实现arguments
变相有slice
这个方法。 - 这就是说:
Array.prototype.slice.call(arguments,0)
这句里,就是把arguments
当做当前对象
也就是说 要调用的是arguments
的slice
方法,后面的 参数 0 也就成了slice
的第一个参数,slice(0)
就是获取所有。
**补充: **
将函数的实际参数转换成数组的方法
方法一:var args = Array.prototype.slice.call(arguments);
方法二:var args = [].slice.call(arguments, 0);
方法三:
var args = [];
for (var i = 1; i < arguments.length; i++) {
args.push(arguments[i]);
}
最后,附个转成数组的通用函数
var toArray = function(s){
//try语句允许我们定义在执行时进行错误测试的代码块。
//catch 语句允许我们定义当 try 代码块发生错误时,所执行的代码块。
try{
return Array.prototype.slice.call(s);
} catch(e){
var arr = [];
for(var i = 0,len = s.length; i < len; i++){
//arr.push(s[i]);
arr[i] = s[i]; //据说这样比push快
}
return arr;
}
}
参考资料:
Array.prototype.slice.call()方法详解
对[].slice.call(arguments,1) 的一丢丢见解
JavaScript arguments对象
JavaScript Function.call() 函数详解