一些写法的理解

139 阅读1分钟

[].shift.call(arguments)

call 手写

Function.prototype.call = function (context) {

  context = context ? Object(context) : window;
  context.fn = this;

  // 执行该函数
  let args = [...arguments].slice(1);
  let result = context.fn(...args);

  // 删除该函数
  delete context.fn;
  // 注意:函数是可以有返回值的
  return result;
};

shift用法

shift 方法并不局限于数组:这个方法能够通过 call 或 apply 方法作用于类似数组的对象上。但是对于没有 length 属性(从 0 开始的一系列连续的数字属性的最后一个)的对象,调用该方法可能没有任何意义。

shift普通调用

const array1 = [1, 2, 3];

const firstElement = array1.shift();
//shift 里面的this 是array1

相似的slice

function list() {
  return Array.prototype.slice.call(arguments);
}

var list1 = list(1, 2, 3); // [1, 2, 3]
Copy to Clipboard
除了使用 Array.prototype.slice.call(arguments),你也可以简单的使用 [].slice.call(arguments) 来代替。另外,你可以使用 bind 来简化该过程。
/**
 * 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 ES2015, 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;
    };
  }
})();
// ES5
var arg1 = Array.prototype.slice.call(arguments);
var arg2 = [].slice.call(arguments);

// ES6
var arg3 = Array.from(arguments);
var arg4 = [...arguments];

总结

sliceshift等 类似 api 对 内部this的处理

  • this
    • 是数组
    • 是类数组
    • xxx
function testErrorShift() {
  return arguments.shift(); // arguments不是数组类型
}
testErrorShift();

// 改变内部this,达到数据的处理
function testshift() {
  return [].shift.call(arguments);
}

console.log(testshift(1, 2, 3, 4, 5));

考察

  • this 的指向
  • 原生数组 api 对内部this的处理
  • this的改变方法
  • 原型与原型链的考察
  • 剩余运算符与扩展运算符
  • 类数组