我遇到了将Array原型应用于本机对象的两种方法:
arr = Array.prototype.slice.call(obj);
arr = [].slice.call(obj);
以类似的方式,获取类似于本机数组的对象的真实类型:
type = Object.prototype.toString.call(obj);
type = {}.toString.call(obj);
一个简单的测试:
function fn() {
console.log(
Array.prototype.slice.call(arguments),
[].slice.call(arguments),
Object.prototype.toString.call(arguments),
{}.toString.call(arguments)
);
}
fn(0,1);
小提琴:http://jsfiddle.net/PhdmN/
他们看起来和我一模一样;第一种语法使用得更频繁,但第二种语法肯定更短。使用较短的语法时是否有任何缺点?
答案 0 :(得分:26)
它们在功能上是相同的。
但是,Array
对象可能会被覆盖,导致第一种方法失败。
//Example:
Array = {};
console.log(typeof Array.prototype.slice); // "undefined"
console.log(typeof [].slice); // "function"
文字方法创建Array
的新实例(与Array.prototype.
方法相对)。两种方法的基准:http://jsperf.com/bbarr-new-array-vs-literal/3
当您打算多次使用该方法时,最佳做法是缓存方法:
var slice = Array.prototype.slice; //Commonly used
var slice = [].slice;
- 如果您担心Array
的存在,或者您只是喜欢较短的语法。答案 1 :(得分:1)
这是一个有趣的问题!让我们分别介绍每种方法的优点(✔️)和缺点(❌):
[].slice
[.slice
是错字。slice
)。与您所想并在各处阅读的内容完全相反, [].slice.call(...)
不会实例化一个新的空Array
只是为了访问其{{1 }}属性!。
现在(已经超过5年了 –截至2018年底), JIT编译(1)包含在所有运行JavaScript的地方(除非您仍然使用IE8或更低版本浏览网页。
此机制允许JS引擎执行以下操作:(2)
...直接
slice
和{strong>静态解析为一次[].slice
的直接引用,并且只有一个可配置的属性访问:Array.prototype
>
forEach
Array.prototype.slice
)在您尝试运行代码之前看起来还不错。❌:运行速度较慢
Array.prorotype.slice
是:(2)
...查找整个范围,以获取
Array.prototype.slice
参考,直到遍历所有范围为止(直到全局一个...),因为您可以您随时可以命名变量Array
。达到全局范围并找到本机后,引擎将访问其proottype,然后访问其方法
...
O(N)范围分辨率+ 2个属性访问权限(Array
和.prototype
)。
✔️:允许您无缝地适应将严格阻止您以.forEach
,(
或[
开头的行的任何编码约定
绝对是一件好事。
`
几乎在所有方面都更好。免责声明:请注意,实际上,任何一个都没有比另一个更有效地运行更快。这不是您应用程序的瓶颈。