javascript 中 [].slice.call 的解释?
Posted
技术标签:
【中文标题】javascript 中 [].slice.call 的解释?【英文标题】:Explanation of [].slice.call in javascript? 【发布时间】:2011-01-08 16:52:29 【问题描述】:我偶然发现了这个将 DOM NodeList 转换为常规数组的简洁快捷方式,但我必须承认,我并不完全理解它是如何工作的:
[].slice.call(document.querySelectorAll('a'), 0)
所以它从一个空数组[]
开始,然后slice
用于将call
的结果转换为一个新数组是吗?
我不明白的是call
。那如何将 document.querySelectorAll('a')
从 NodeList 转换为常规数组?
【问题讨论】:
Array.prototype.slice.call(document.querySelectorAll('a'));
是编写您编写的代码块的正确方法。
顺便说一句,现代(直观易懂)的 ES6 方法是 Array.from
。所以例如这会做同样的事情: Array.from(document.querySelectorAll('a'));
这能回答你的问题吗? how does Array.prototype.slice.call() work?
【参考方案1】:
这里发生的情况是,您调用slice()
,就好像它是使用call()
的NodeList
的函数一样。 slice()
在这种情况下所做的是创建一个空数组,然后遍历它正在运行的对象(最初是一个数组,现在是一个 NodeList
)并继续将该对象的元素附加到它创建的空数组中,即最终回来了。这是article on this。
编辑:
所以它以一个空数组[]开头,然后使用slice 将调用结果转换为新数组好吗?
这是不对的。 [].slice
返回一个函数对象。一个函数对象有一个函数call()
,它调用将call()
的第一个参数分配给this
的函数;换句话说,让函数认为它是从参数(document.querySelectorAll('a')
返回的 NodeList
)而不是数组调用的。
【讨论】:
这里还要注意,虽然这在语义上等同于说Array.prototype.slice.call(...)
,但它实际上实例化一个数组对象([]
)只是为了访问它的原型切片方法。那是浪费的实例化。说Array.prototype.slice.call(...)
更简洁,尽管如果你在数数的话,你会在你的 JS 中添加几个字符......
请注意,这仅适用于 IE 8 及更低版本的 Array 对象,因此您将无法克隆 NodeList
s
@quixoto []
更可靠,因为Array
可以被其他东西覆盖。如果您需要重用Array#slice
,最好将其缓存起来。
如果其他人正在寻找在 IE8 中执行此操作的方法,请查看此问题 ***.com/questions/3199588/…
我实际上在backbone.js源代码中看到了这种模式:var array = []; var push = array.push; var slice = array.slice; var splice = array.splice;
他这样做是为了@MathiasBynens提到的安全问题吗?【参考方案2】:
在 javascript 中,一个对象的方法可以在运行时绑定到另一个对象。简而言之,javascript允许一个对象“借用”另一个对象的方法:
object1 =
name: 'Frank',
greet()
alert(`Hello $this.name`);
;
object2 =
name: 'Andy'
;
// Note that object2 has no greet method,
// but we may "borrow" from object1:
object1.greet.call(object2); // Will show an alert with 'Hello Andy'
函数对象的call
和apply
方法(在JavaScript 中,函数也是对象)允许您执行此操作。因此,在您的代码中,您可以说 NodeList 正在借用数组的 slice 方法。 .slice()
返回另一个数组作为其结果,它将成为您可以使用的“转换后的”数组。
【讨论】:
Bang on ? javascript 对象函数的抽象概念解释。现在,您可以将其应用于Array.prototype
aka [].prototype
的call
函数。【参考方案3】:
它从Array
中检索slice
函数。然后它调用该函数,但使用document.querySelectorAll
的结果作为this
对象而不是实际数组。
【讨论】:
【参考方案4】:这是一种将类数组对象转换为真实数组的技术。
其中一些对象包括:
arguments
在函数中
NodeList(记住它们的内容在被获取后可能会改变!所以将它们转换为数组是一种冻结它们的方法)
jQuery 集合,又名 jQuery 对象(一些文档:API、type、learn)
这有很多用途,例如对象通过引用传递,而数组通过值传递。
另外,请注意第一个参数 0
可以省略,thorough explanation here。
为了完整起见,还有jQuery.makeArray()。
【讨论】:
【参考方案5】:如何将
document.querySelectorAll('a')
从NodeList
到常规数组?
这是我们拥有的代码,
[].slice.call(document.querySelectorAll('a'), 0)
我们先拆吧,
[] // Array object
.slice // Accessing the function 'slice' present in the prototype of Array
.call // Accessing the function 'call' present in the prototype of function object(slice)
(document.querySelectorAll('a'),0)
// 'call' can have arguments like, (thisArg, arg1,arg2...n).
// So here we are passing the 'thisArg' as an array like object,
// that is a 'nodeList'. It will be served as 'this' object inside of slice function.
// And finally setting 'start' argument of slice as '0' and leaving the 'end'
// argument as 'undefined'
步骤:1 执行call
函数
call
内,除了thisArg
,其余的参数
将被附加到参数列表中。
现在函数slice
将通过将其this
值绑定为来调用
thisArg
(类似数组的对象来自document.querySelector
)和参数列表。即] 参数start
包含0
步骤:2 执行在call
内部调用的slice
函数
start
将分配给变量 s
作为 0
由于end
是undefined
,this.length
将存储在e
一个空数组将被存储在一个变量a
进行上述设置后,将发生以下迭代
while(s < e)
a.push(this[s]);
s++;
填满的数组a
将作为结果返回。
P.S 为了更好地理解我们的场景,call 和 slice 的原始算法已经忽略了我们的上下文所必需的一些步骤。
【讨论】:
非常好的一步一步的解释。惊人的!谢谢你:) 很好的解释。【参考方案6】:[].slice.call(document.querySelectorAll('.slide'));
1. The querySelectorAll() method returns all elements in the document that matches a specified selector(s).
2. The call() method calls a function with a given this value and arguments provided individually.
3. The slice() method returns the selected elements in an array, as a new array object.
so this line return the array of [object htmlDivElement]. Here is the six div with classname "slide" so array length will be 6.
<div class="slideshow">
<div class="slide">
first slider1
</div>
<div class="slide">
first slider2
</div>
<div class="slide">
first slider3
</div>
<div class="slide">
first slider4
</div>
<div class="slide">
first slider5
</div>
<div class="slide">
first slider6
</div>
</div>
<script type="text/javascript">
var arraylist = [].slice.call(document.querySelectorAll('.slide'));
alert(arraylist);
</script>
【讨论】:
【参考方案7】:来自 ES6:只需使用 Array.from(element.children) 或 Array.from(length: 5)
制作数组【讨论】:
【参考方案8】:这也可能有帮助。
切片方法
说明:
slice 不会改变原始数组。它返回原始数组中元素的浅表副本。原始数组的元素被复制到返回的数组中。slice() 方法将数组的一部分的浅拷贝返回到从开始到结束(不包括结束)选择的新数组对象中,其中开始和结束表示该数组中项目的索引。原始数组不会被修改。 查看更多:Reference/Global_Objects/Array/slice
调用方法
说明:
call() 允许分配属于一个对象的函数/方法并为不同的对象调用。
call() 方法使用给定的 this 值和单独提供的参数调用函数。 call() 为函数/方法提供了 this 的新值。使用 call(),你可以编写一次方法,然后在另一个对象中继承它,而无需为新对象重写方法。
查看更多:Reference/Global_Objects/Function/call
【讨论】:
以上是关于javascript 中 [].slice.call 的解释?的主要内容,如果未能解决你的问题,请参考以下文章