手写数组方法

map

V8源码

Array.prototype.map = function(callbackFn, thisArg) {
            // 处理数组类型异常
            if (this === null || this === undefined) {
                throw new TypeError("Cannot read property 'map' of null or undefined");
            }
            // 处理回调类型异常
            if (Object.prototype.toString.call(callbackfn) != "[object Function]") {
                throw new TypeError(callbackfn + ' is not a function')
            }
            // 草案中提到要先转换为对象
            let O = Object(this);
            let T = thisArg;

            let len = O.length >>> 0;
            let A = new Array(len);
            for(let k = 0; k < len; k++) {
                if (k in O) {
                let kValue = O[k];
                // 依次传入this, 当前项,当前索引,整个数组
                let mappedValue = callbackfn.call(T, KValue, k, O);
                A[k] = mappedValue;
                }
            }
            return A;
        }   

注意点:

  • length >>> 0, 字面意思是指"右移 0 位",但实际上是把前面的空位用0填充,这里的作用是保证len为数字且为整数;
  • 循环中使用 in 来进行原型链查找。同时,如果没有找到就不处理,能有效处理稀疏数组的情况。如果用 hasOwnProperty 是有问题的,它只能找私有属性;

 reduce

V8源码

Array.prototype.reduce  = function(callbackfn, initialValue) {
  // 处理数组类型异常
  if (this === null || this === undefined) {
    throw new TypeError("Cannot read property 'reduce' of null or undefined");
  }
  // 处理回调类型异常
  if (Object.prototype.toString.call(callbackfn) != "[object Function]") {
    throw new TypeError(callbackfn + ' is not a function')
  }
  let O = Object(this);
  let len = O.length >>> 0;
  let k = 0;
  let accumulator = initialValue;
  if (accumulator === undefined) {
    for(; k < len ; k++) {
      // 查找原型链
      if (k in O) {
        accumulator = O[k];
        k++;
        break;
      }
    }
    // 循环结束还没退出,就表示数组全为空
    throw new Error('Each element of the array is empty');
  }
  for(;k < len; k++) {
    if (k in O) {
      accumulator = callbackfn.call(undefined, accumulator, O[k], O);
    }
  }
  return accumulator;
}

filter

Array.prototype.filter = function(callbackfn, thisArg) {
  // 处理数组类型异常
  if (this === null || this === undefined) {
    throw new TypeError("Cannot read property 'filter' of null or undefined");
  }
  // 处理回调类型异常
  if (Object.prototype.toString.call(callbackfn) != "[object Function]") {
    throw new TypeError(callbackfn + ' is not a function')
  }
  let O = Object(this);
  let len = O.length >>> 0;
  let resLen = 0;
  let res = [];
  for(let i = 0; i < len; i++) {
    if (i in O) {
      let element = O[i];
      if (callbackfn.call(thisArg, O[i], i, O)) {
        res[resLen++] = element;
      }
    }
  }
  return res;
}

push

Array.prototype.push = function(...items) {
  let O = Object(this);
  let len = this.length >>> 0;
  let argCount = items.length >>> 0;
  // 2 ** 53 - 1 为JS能表示的最大正整数
  if (len + argCount > 2 ** 53 - 1) {
    throw new TypeError("The number of array is over the max value restricted!")
  }
  for(let i = 0; i < argCount; i++) {
    O[len + i] = items[i];
  }
  let newLength = len + argCount;
  O.length = newLength;
  return newLength;
}

pop

Array.prototype.pop = function() {
  let O = Object(this);
  let len = this.length >>> 0;
  if (len === 0) {
    O.length = 0;
    return undefined;
  }
  len --;
  let value = O[len];
  delete O[len];
  O.length = len;
  return value;
}

 

posted on 2018-05-29 20:55  紅葉  阅读(214)  评论(0编辑  收藏  举报