search

Home  >  Q&A  >  body text

javascript - Array.proto.slice.call(doc.querySelectorAll("[bind]"),0)的作用是什么?

Array.prototype.slice.call(document.querySelectorAll("[data-bind]"),0);

的作用是什么?为什么可以这样做?

阿神阿神2896 days ago355

reply all(7)I'll reply

  • 阿神

    阿神2017-04-10 17:35:46

    作用是将document.querySelectorAll("[data-bind]")返回的NodeList(Array-like Object)转换为数组。

    首先了解什么是Array-like Object:

    Array-like objects look like arrays. They have various numbered elements and a length property. But that’s where the similarity stops. Array-like objects do not have any of Array’s functions, and for-in loops don’t even work!

    将Array-like Object转化为数组比较直白的方式是:

    var nodeList = document.querySelectorAll("[data-bind]");
    var array = [];
    for(var i = 0; i < nodeList.length; i ++)
        array.push(nodeList[i]);

    但是调用Array原型中的slice方法也可以完成转换。参考Array.slice中的“类数组(Array-like)对象”这部分:

    slice 方法可以用来将一个类数组(Array-like)对象/集合转换成一个数组。你只需将该方法绑定到这个对象上。下述代码中 list 函数中的 arguments 就是一个类数组对象

    所以,可以推测slice内部肯定也是通过length和[i]索引来操作数组或者类数组对象的。

    reply
    0
  • PHP中文网

    PHP中文网2017-04-10 17:35:46

    这段代码的作用是将document.querySelectorAll获取到的值转化为一个数据对象。因为document.querySelectorAll获取到的是nodeList,只能算类数组,是没有数组相关方法和特性的。

    reply
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-10 17:35:46

    也可以使用Array.from()来将其转换为数组

    reply
    0
  • 怪我咯

    怪我咯2017-04-10 17:35:46

    直接用document.querySelectorAll()取得的“数组”,看似数组,却并不是真正的数组,虽然它有
    .length属性,但是它并不是Array对象创造的一个实例,不信你查看一下实例的.__proto__属性。

    这造成的问题就是,我们无法使用各种数组方法来操作这个所谓的“数组”,因为所有数组方法都来自于Array.prototype。如果我们想把它变成真正的数组,就得用Array.prototype.slice.call(obj,0)来创建一个继承自Array的真正数组。

    实际上,docment.querySelectorAll()document.getElementsByTagName()取得的值,叫做NodeList,是一种类数组。类似的还有函数的arguments,也是一种类数组,我们也可以使用同样的方法来让它成为真正的数组

    reply
    0
  • PHPz

    PHPz2017-04-10 17:35:46

    document.querySelectorAll("[data-bind]")返回的是一个类数组对象和数组很相似,但它又不是数组对象,不能直接用数组的方法,所以就有了call和apply函数,用来间接调用函数
    JavaScript权威指南8.7.3有详细的介绍

    reply
    0
  • 阿神

    阿神2017-04-10 17:35:46

    你看下slice的shim就明白原理了。

    /**
     * Shim for "fixing" IE's lack of support (IE < 9) for applying slice
     * on host objects like NamedNodeMap, NodeList, and HTMLCollection
     * (technically, since host objects have been implementation-dependent,
     * at least before ES6, IE hasn't needed to work this way).
     * Also works on strings, fixes IE < 9 to allow an explicit undefined
     * for the 2nd argument (as in Firefox), and prevents errors when
     * called on other DOM objects.
     */
    (function () {
      'use strict';
      var _slice = Array.prototype.slice;
    
      try {
        // Can't be used with DOM elements in IE < 9
        _slice.call(document.documentElement);
      } catch (e) { // Fails in IE < 9
        // This will work for genuine arrays, array-like objects, 
        // NamedNodeMap (attributes, entities, notations),
        // NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes),
        // and will not fail on other DOM objects (as do DOM elements in IE < 9)
        Array.prototype.slice = function(begin, end) {
          // IE < 9 gets unhappy with an undefined end argument
          end = (typeof end !== 'undefined') ? end : this.length;
    
          // For native Array objects, we use the native slice function
          if (Object.prototype.toString.call(this) === '[object Array]'){
            return _slice.call(this, begin, end); 
          }
    
          // For array like object we handle it ourselves.
          var i, cloned = [],
            size, len = this.length;
    
          // Handle negative value for "begin"
          var start = begin || 0;
          start = (start >= 0) ? start : Math.max(0, len + start);
    
          // Handle negative value for "end"
          var upTo = (typeof end == 'number') ? Math.min(end, len) : len;
          if (end < 0) {
            upTo = len + end;
          }
    
          // Actual expected size of the slice
          size = upTo - start;
    
          if (size > 0) {
            cloned = new Array(size);
            if (this.charAt) {
              for (i = 0; i < size; i++) {
                cloned[i] = this.charAt(start + i);
              }
            } else {
              for (i = 0; i < size; i++) {
                cloned[i] = this[start + i];
              }
            }
          }
    
          return cloned;
        };
      }
    }());

    reply
    0
  • 大家讲道理

    大家讲道理2017-04-10 17:35:46

    找到所有有data-bind的元素,并取第一个

    reply
    0
  • Cancelreply