【问题标题】:Explanation of [].slice.call in javascript?javascript 中 [].slice.call 的解释?
【发布时间】: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?

标签: javascript arrays call slice


【解决方案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 对象,因此您将无法克隆 NodeLists
  • @quixoto [] 更可靠,因为Array 可以被其他东西覆盖。如果您需要重用Array#slice,最好将其缓存起来。
  • 如果其他人正在寻找在 IE8 中执行此操作的方法,请查看此问题 stackoverflow.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'

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

【讨论】:

  • Bang on ? javascript 对象函数的抽象概念解释。现在,您可以将其应用于Array.prototype aka [].prototypecall 函数。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    其中一些对象包括:

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

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

    另外,请注意第一个参数 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
      • 由于endundefinedthis.length 将存储在e
      • 一个空数组将被存储在一个变量a
      • 进行上述设置后,将发生以下迭代

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

      P.S 为了更好地理解我们的场景,callslice 的原始算法已经忽略了我们的上下文所必需的一些步骤。

      【讨论】:

      • 非常好的一步一步的解释。惊人的!谢谢你:)
      • 很好的解释。
      【解决方案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

          【讨论】:

            猜你喜欢
            • 2021-07-21
            • 1970-01-01
            • 2012-09-14
            • 2011-04-21
            • 1970-01-01
            • 1970-01-01
            • 2017-04-01
            • 1970-01-01
            • 2015-03-01
            相关资源
            最近更新 更多