关于用slice将类数组转换成数组的原理?

如题我要将一个类数组转换成真正的数组在es6之前要使用slice去处理,像对函数的对象arguments进行转换成数组,可以用 Array.prototype.slice.apply(arguments);谁能讲解一下这段里面到底是一个怎样的过程,为什么它能够实现将它转化成数组?

阅读 7.4k
3 个回答

直接看slice怎么实现的吧。其实就是将array-like对象通过下标操作放进了新的Array里面:

// 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;
    };

可以查阅v8源码,链接在这里,第587行链接

照着规范的流程,自己看看推演一下就明白了:
Array.prototype.slice (start, end)

简而言之一句话,当slice()没有输入参数的时候,会创建一个新数组,然后把当前数组的所有元素扔进去,最后返回这个新数组。

推荐问题
宣传栏