'Array.prototype.slice.call'如何工作?

2022-08-29 23:04:11

我知道它是用来做一个真正的,但我不明白使用时会发生什么。argumentsArrayArray.prototype.slice.call(arguments);


答案 1

在引擎盖下发生的事情是,当被正常调用时,是一个数组,然后它只是迭代该数组,并完成其工作。.slice()this

函数中如何成为数组?因为当您这样做时:this.slice()

object.method();

...将自动成为 中的 值。所以与:objectthismethod()

[1,2,3].slice()

...数组设置为 中的 值。[1,2,3]this.slice()


但是,如果您可以用其他东西代替价值呢?只要您替换的任何内容都有一个数字属性,并且有一堆是数字索引的属性,它就应该有效。这种类型的对象通常称为类似数组的对象this.length

和 方法允许您手动设置函数中的 值。因此,如果我们将 in 的值设置为类似数组的对象,则只假设它正在与 Array 一起工作,并且将执行其操作。.call().apply()thisthis.slice().slice()

以这个普通的物体为例。

var my_object = {
    '0': 'zero',
    '1': 'one',
    '2': 'two',
    '3': 'three',
    '4': 'four',
    length: 5
};

这显然不是一个数组,但是如果您可以将其设置为 的值,那么它将正常工作,因为它看起来足够像一个数组来正常工作。this.slice().slice()

var sliced = Array.prototype.slice.call( my_object, 3 );

示例:http://jsfiddle.net/wSvkv/

正如您在控制台中看到的,结果是我们所期望的:

['three','four'];

因此,当您将对象设置为 的值时,就会发生这种情况。因为有一个属性和一堆数字索引,就像它在一个真正的数组上工作一样。argumentsthis.slice()arguments.length.slice()


答案 2

该对象实际上不是 Array 的实例,并且没有任何 Array 方法。因此,将不起作用,因为参数对象没有切片方法。argumentsarguments.slice(...)

数组确实具有此方法,并且由于对象与数组非常相似,因此两者是兼容的。这意味着我们可以将数组方法与参数对象一起使用。由于数组方法是在构建数组时考虑数组的,因此它们将返回数组而不是其他参数对象。arguments

那么为什么要使用?是我们从 () 创建新数组的对象,这些新数组是传递的方法和属性,如 slice。这些方法存储在对象中。因此,为了提高效率,我们不是通过 或 访问切片方法,而是直接从原型中获取它。这样我们就不必初始化新数组。Array.prototypeArraynew Array()[Class].prototype(new Array()).slice.call()[].slice.call()

但是,为什么我们首先必须这样做呢?好吧,正如你所说,它将参数对象转换为数组实例。然而,我们使用切片的原因比任何东西都更像是“黑客”。slice 方法将采用一个数组的切片(您猜对了),并将该切片作为新数组返回。不向它传递任何参数(除了参数对象作为其上下文)会导致 slice 方法获取传递的“数组”(在本例中为参数对象)的完整块,并将其作为新数组返回。