关于JavaScript的切片和拼接方法的问题

时间:2009-11-22 03:10:46

标签: javascript arrays arguments slice

我遇到了以下代码:

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

3 个答案:

答案 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