javascript 中 [].slice.call 的解释?

IT技术 javascript arrays call slice
2021-02-11 07:36:32

我偶然发现了这个将 DOM NodeList 转换为常规数组的简洁快捷方式,但我必须承认,我并不完全理解它是如何工作的:

[].slice.call(document.querySelectorAll('a'), 0)

所以它以一个空数组开始[],然后slice用于将结果转换call为一个新数组是吗?

我不明白的一点是call. 那如何document.querySelectorAll('a')从 NodeList 转换为常规数组?

6个回答

这里发生的事情是你调用slice()好像它是一个NodeListusing的函数call()什么slice()做在这种情况下是通过运行它的对象(最初的数组,现在创建一个空数组,然后迭代NodeList),并保留追加该对象的元素,它创建的空数组,这是最终返回。这是一篇关于此文章

编辑:

所以它以一个空数组[]开头,然后切片用于将调用结果转换为新数组是吗?

那是不对的。[].slice返回一个函数对象。一个函数对象有一个函数call(),它调用分配给call()to的第一个参数的函数this换句话说,使函数认为它是从参数(由NodeList返回的document.querySelectorAll('a'))而不是从数组调用的

这里还要注意,虽然这在语义上等同于 say Array.prototype.slice.call(...),但它实际上实例化了一个数组对象 ( []) 只是为了访问它的原型 slice 方法。那是浪费的实例化。Array.prototype.slice.call(...)改为更清晰,尽管如果您在计算,您可以在 JS 中添加几个字符...
2021-03-20 07:36:32
请注意,这仅适用于 IE 8 及以下的 Array 对象,因此您将无法克隆NodeLists
2021-03-20 07:36:32
我实际上在backbone.js 源代码中看到了这种模式: var array = []; var push = array.push; var slice = array.slice; var splice = array.splice;他这样做是为了@MathiasBynens 提到的安全问题吗?
2021-03-22 07:36:32
@quixoto[]更可靠,因为Array可以被其他东西覆盖。如果需要重用Array#slice,最好缓存它。
2021-03-25 07:36:32
如果其他人正在寻找在 IE8 中执行此操作的方法,请查看此问题stackoverflow.com/questions/3199588/...
2021-03-28 07:36:32

在 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'

函数对象callapply方法(在 JavaScript 中,函数也是对象)允许您这样做。因此,在您的代码中,您可以说 NodeList 借用了数组的 slice 方法。.slice()返回另一个数组作为其结果,它将成为您可以使用的“转换后”数组。

猛击 🎯 对 javascript 对象函数的抽象概念解释。现在,您可以将其应用于akacall功能Array.prototype[].prototype
2021-03-21 07:36:32

sliceArray. 然后它调用该函数,但使用 的结果document.querySelectorAll作为this对象而不是实际数组。

它是一种将类数组对象转换为真实数组的技术。

其中一些对象包括:

  • arguments 在函数中
  • NodeList(记住它们的内容在被获取后可以改变!所以将它们转换为数组是一种冻结它们的方法)
  • jQuery 集合,又名 jQuery 对象(一些文档:API类型学习

这有很多用途,例如对象通过引用传递而数组通过值传递。

另外,注意第一个参数0可以省略,这里有详尽的解释

为了完整起见,还有jQuery.makeArray()

那如何document.querySelectorAll('a')从 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 执行slice内部调用函数call

  • start将被分配给一个变量s作为0
  • 因为endundefinedthis.length将被存储在e
  • 一个空数组将存储在一个变量中 a
  • 进行上述设置后,将进行以下迭代

    while(s < e) {
      a.push(this[s]);
      s++;
    }
    
  • 填充的数组a将作为结果返回。

PS 为了更好地理解我们的场景,我们的上下文所需的一些步骤已从callslice的原始算法中忽略

非常好的一步一步的解释。惊人的!谢谢 :)
2021-04-08 07:36:32
很好的解释。
2021-04-11 07:36:32