我遇到了以下代码:
var f = function () {
var args = Array.prototype.slice.call(arguments).splice(1);
// some more code
};
基本上,args
中的结果是一个数组,它是arguments
的副本而没有第一个元素。
但是我无法理解的是为什么f
的{{1}}(这是一个将函数的输入参数保存到类数组对象中的对象)对象被传递给{ {1}}方法以及arguments
如何删除第一个元素(位于索引0处)。
有人可以帮我解释一下吗?
P.S。代码来自此partial application function
答案 0 :(得分:40)
<注>
来自linked answer的实际代码是:
var args = Array.prototype.slice.call(arguments, 1);
即。 “切片”,而不是“拼接”
< /注释>
首先,slice
方法通常用于make a copy of the array it's called on:
var a = ['a', 'b', 'c'];
var b = a.slice(); // b is now a copy of a
var c = a.slice(1); // c is now ['b', 'c']
所以简短的回答是代码基本上是模仿的:
arguments.slice(1); // discard 1st argument, gimme the rest
但是你不能直接这样做。 special arguments
object(在所有JavaScript函数的执行上下文中可用),尽管Array- 类似于,它支持使用数字键通过[]
运算符进行索引,但实际上并不是阵列;你不能.push
加上它,.pop
关闭它,或.slice
它等等。
代码完成此操作的方式是“欺骗”slice
函数(在arguments
对象上无法再次使用)以在 {的上下文中运行 {1}},通过Function.prototype.call
:
arguments
Array.prototype.slice // get a reference to the slice method
// available on all Arrays, then...
.call( // call it, ...
arguments, // making "this" point to arguments inside slice, and...
1 // pass 1 to slice as the first argument
)
完成同样的事情,但对Array.prototype.slice.call(arguments).splice(1)
进行无关的调用,从splice(1)
返回的数组中删除元素,从index {{{1}开始1}}并继续到数组的末尾。 Array.prototype.slice.call(arguments)
在IE中不起作用(技术上缺少第二个参数,告诉它删除了IE和ECMAScript需要多少项)。
答案 1 :(得分:3)
var args = Array.prototype.slice.call(arguments).splice(1);
首先获取arguments
(*)的副本,然后从中删除除第一项之外的所有项目(以非标准方式),并将要删除的项目分配给args
。
生成,然后更改和丢弃的额外数组是非常多余的。最好这样说 - 因为您链接的答案中的版本确实如此:
var args = Array.prototype.slice.call(arguments, 1);
部分功能应用程序也是function.bind
方法的一个功能,由ECMAScript Fifth Edition标准化。在浏览器实现它之前,您可以从this answer的底部选择一个后备JS原生版本。
*:array.slice()
是复制数组的正常习惯用法,array.slice(1)
用于获取尾部。它通过Array.prototype
显式调用,因为arguments
不是一个数组,即使它看起来像一个数组,所以没有正常的数组方法。这是JavaScript的另一个奇怪的错误。
你经常会看到人们在不是数组的对象上使用Array.prototype
方法; ECMAScript第三版标准不再说明可以为arguments
阵列做,但不,你也可以在其他类似的阵列上做是宿主对象,例如NodeList或HTMLCollection。虽然您今天可能会在许多浏览器中调用非数组上的Array.prototype
方法,但实际上安全的唯一方法是arguments
。
答案 2 :(得分:0)
splice的返回值是已删除元素的数组, 但原始数组(或类似数组的对象)在拼接索引处被截断。
使用切片制作副本会保留原始参数数组, 大概是在以后的功能中使用。
在这种情况下,args = [].slice.call(arguments, 1)
function handleArguments(){
var A= [].slice.call(arguments).splice(1);
//arguments is unchanged
var s= 'A='+A+'\narguments.length='+arguments.length;
var B= [].splice.call(arguments, 1);
// arguments now contains only the first parameter
s+= '\n\nB='+B+'\narguments.length='+arguments.length;
return s;
}
// test
alert(handleArguments(1, 2, 3, 4));
returned value:
//var A= [].slice.call(arguments).splice(1);
A=2,3,4
arguments.length=4
//var B= [].splice.call(arguments, 1);
B=2,3,4
arguments.length=1