Array.prototype.slice.call(array, 0) 有啥用?

Posted

技术标签:

【中文标题】Array.prototype.slice.call(array, 0) 有啥用?【英文标题】:What's the use of Array.prototype.slice.call(array, 0)?Array.prototype.slice.call(array, 0) 有什么用? 【发布时间】:2011-07-05 22:14:31 【问题描述】:

我刚刚在浏览 Sizzle 的源代码时,偶然发现了这行代码:

array = Array.prototype.slice.call( array, 0 );

我查看了函数是什么,但我得出的结论是它只是返回从索引 0 开始的数组的所有元素,并将整个元素放入数组中,即它实际上并没有做任何事情。

那么这行代码有什么用呢?我错过了什么?

编辑:这是来自https://github.com/jquery/sizzle/blob/master/sizzle.js#L863的第863行。

【问题讨论】:

调用array.slice(0) 似乎有点古怪,它会复制数组。我不明白为什么它会以如此难以理解的方式被调用。 上下文决定一切。 array 标识符没有引用实际的数组。 【参考方案1】:

对于像getElementsByTagName 这样的大多数操作,DOM 通常会返回一个NodeList

虽然NodeList 几乎感觉像是一个数组,但事实并非如此。它有一个像数组一样的length 属性,以及一个方法item(index) 来访问给定索引处的对象(也可以使用[index] 表示法访问),但这就是相似性结束的地方。

所以为了能够使用美妙的array methods 而无需将它们全部重写为NodeList,上面的行很有用。

将它转换为数组的另一个用途是使列表静态化。 NodeLists 通常是实时的,这意味着如果发生文档更改,NodeList 对象会自动更新。如果返回给您的 jQuery 对象在您眼皮底下不断变化,这可能会导致问题。试试下面的snippet 来测试 NodeList 的活跃度。

var p = document.getElementsByTagName('p');
console.log(p.length); // 2
document.body.appendChild(document.createElement('p'));
// length of p changes as document was modified
console.log(p.length); // 3

【讨论】:

废话,这个答案让我离真正拥抱 JS 更近了一步。多年来,我一直希望它会消失……无论如何,+1 给你。 我提出的一个问题是:你怎么知道数组方法可以应用于哪些对象?显然,它是任何具有长度属性和整数属性名称的对象(从零开始?)。我还了解到“参数”变量是一个类似对象的数组,但不是一个实际的数组(我不知道)。答案就在这里:***.com/questions/7056925/… @zod:如果您查看V8's implementation,那么doesn't seem 会发生任何神奇的事情。它使用.length 来确定范围,然后执行for 循环来复制正确的元素(只需要一个带有数字键的对象)。【参考方案2】:

这里发生的是 Sizzle 正在从一个类似数组的对象中创建一个实际的数组。类数组对象不一定有 slice() 方法,所以必须直接调用原型方法。 makeArray() 返回该类数组对象的副本,该对象是一个实际数组,可以在其他地方使用。

有关类似数组的对象的更多信息,请参阅here。

【讨论】:

【参考方案3】:

正如 BoltClock 所说,它制作了一个数组的(浅)副本。它还可以用于复制几乎为数组的东西,例如arguments 内置函数,它有一个长度和项,但其原型链中没有数组(因此没有切片方法)。

【讨论】:

我是这么认为的,但它会将结果分配回相同的array,所以我无法弄清楚到底发生了什么。 请问为什么var 没有放在前面?如果制作了副本,那么它不会是一个新变量,即var @BoltClock,嗯……这很奇怪。也许是将 Array 原型赋予一些不真实的东西,比如参数或 jQuery 集。 @pimvdb,这取决于上下文。这可能只是一个错误:) 这样做的一个可能效果是删除数组中的任何命名成员。 (当然不会影响原型。)。就像你有 var array = ['zero','one','two']; array['someProp'] = 'someValue'; 一样,你可以使用问题中的技术摆脱 someProp

以上是关于Array.prototype.slice.call(array, 0) 有啥用?的主要内容,如果未能解决你的问题,请参考以下文章