针对 NodeList 调用 Array.prototype.slice 的目的是什么? [英] What is the purpose of calling Array.prototype.slice against a NodeList?

查看:20
本文介绍了针对 NodeList 调用 Array.prototype.slice 的目的是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找如何迭代 NodeLists,但我遇到了以下代码.

I was looking up how to iterate NodeLists and I came across the following bit of code.

var nodesArray = Array.prototype.slice.call(nodeList);
nodesArray.forEach(function(node) { 
    //...
})

对 NodeList 调用 Array.prototype.slice 的目的是什么?

What is the purpose of calling Array.prototype.slice against a NodeList?

推荐答案

对 NodeList 调用 Array.prototype.slice 的目的是什么?

Array#slice 方法将数组的一部分的浅拷贝返回到新的数组对象中".

The Array#slice method "returns a shallow copy of a portion of an array into a new array object".

Function#call 方法使用给定的 this 值和单独提供的参数调用函数".

The Function#call method "calls a function with a given this value and arguments provided individually".

因为数组是对象,所有的对象属性名称都存储为字符串,并且所有的节点列表都以连续编号的属性名称存储其元素(再次存储为字符串),节点列表可以用作this值对于数组方法.

Because Arrays are Objects, all Object property names are stored as strings, and all NodeLists store their elements with sequential numbered property names (again stored as strings), NodeLists can be used as the this value for Array methods.

将 NodeList 的浅拷贝创建为 Array 允许您在新创建的 Array 上使用其他 Array 方法,而无需使用 Function#call.

Creating a shallow copy of the NodeList as an Array allows you to use other Array methods on the newly created Array without using Function#call.

许多现代浏览器已经实现了NodeList#forEach,虽然该方法仍是候选推荐,并且此时尚未将其纳入规范.我建议谨慎使用该方法,而不是在开放的网络上使用,直到它达到更稳定的状态.

Many modern browsers have implemented NodeList#forEach, though the method is still a candidate recommendation and has not made it into the specification at this point. I recommend using that method with care, and not on the open web, until it has reached a more stable status.

以下是使用 NodeList 作为目标调用 Array 方法的一些其他示例:

Here are some other examples of Array methods being called with a NodeList as the target:

// Convert to an array, then iterate
const nodeArray = Array.prototype.slice.call(nodeList)
nodeArray.forEach(doSomething);

// Iterate NodeList directly without conversion
Array.prototype.forEach.call(nodeList, doSomething);

// Perform operation on each element in NodeList, output results to a new Array
Array.prototype.map.call(nodeList, function(item) { 
    return item; 
}).forEach(doSomething);

// Filter NodeList, output result to a new Array
Array.prototype.filter.call(nodeList, function(item) { 
    return /* condition */; 
}).forEach(doSomething);

<小时>

有许多其他方法可以迭代 NodeList 而不需要使用 Array 方法,这里有更多示例:


There are many other ways that you can iterate a NodeList that don't require the use of Array methods, here are some more examples:

你可以使用一个很好的老式 for 循环,从零开始循环直到我们到达数组的末尾.这种方法一直存在,今天仍然经常使用.与此处提到的其他方法相比,此方法在某种程度上可读性较差,但这一切都归结为您更容易编写的方法.

You can use a good old fashioned for loop, start at zero and loop until we reach the end of the array. This method has been around for ever and is still used regularly today. This method is, somewhat, less readable than other methods mentioned here, but it all comes down to what is easier for you to write.

for(let i = 0; i < nodeList.length; ++i)  doSomething(nodeList[i]);

由于缺乏条件评估,使用向后循环(在可能的情况下)可以减少执行时间.事实上,一些 IDE 会默认将前面的循环转换为下面的结构.

Using a backwards loop (where possible) can save reduce execution time due to a lack of conditional evaluation. In fact, some IDE's will convert the previous loop to the following structure by default.

for(let i = nodeList.length; i--;)  doSomething(nodeList[i]);

您可以使用 while 循环,它需要一个条件语句作为其参数.如果 NodeList.item(n) 超出了 NodeList 的边界,它将返回 null,这将结束循环.

You can use a while loop, which expects a conditional statement as its parameter. If NodeList.item(n) is past the bounds of the NodeList it will return null, which will end the loop.

let i = 0, node;
while((node = nodeList.item(i++))) doSomething(node);

你可以在条件语句中用 for 循环做同样的事情:

You can do the same thing with a for loop in the conditional:

let node;
for(let i = 0; (node = nodeList.item(i)); i++) doSomething(node);

您可以在 Object.keys() 中使用 for...in 循环.请注意,在使用 for...in 循环时必须使用 Object.keys,否则它将遍历不可枚举的属性和可枚举的属性.

You can use a for...in loop with Object.keys(). Note that you have to use Object.keys when using a for...in loop because otherwise it will iterate over the non-enumerable properties as well as the enumerable ones.

Object.keys() 方法返回给定对象自己的可枚举属性的数组,其顺序与 for...in 循环提供的顺序相同(区别在于 for-in 循环在原型链也是如此).
来自: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

The Object.keys() method returns an array of a given object's own enumerable properties, in the same order as that provided by a for...in loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).
From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

for(var i in Object.keys(nodeList))  doSomething(nodeList[i]);

您可以通过从 Array() 检索 Iterator 函数并将其应用于 NodeList 来使用 for...of 循环(ECMAScript 2015+).只要属性是可枚举的,这也适用于对象的大多数其他用途.

You can use a for...of loop (ECMAScript 2015+) by retrieving the Iterator function from Array() and applying it to the NodeList. This will work for most other uses of an object as well, as long as the properties are enumerable.

nodeList[Symbol.iterator] = [][Symbol.iterator];
for(node of nodeList) doSomething(node);

如果您将数组迭代器应用于 NodeList 类的原型,那么无论何时创建 NodeList 的新实例,它都将始终是可迭代的.但是,不建议扩展原生原型.

If you apply the Array Iterator to the prototype of the NodeList class then whenever a new instance of NodeList is created, it will always be iterable. However, it is not advisable to extended native prototypes.

NodeList.prototype[Symbol.iterator] = [][Symbol.iterator];
for(node of nodeList) doSomething(node);

这篇关于针对 NodeList 调用 Array.prototype.slice 的目的是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆