3、数组方法底层实现

Array.prototype.push

Array.prototype.push = function (...items) {
  // ECMA规范规定转为对象进行操作
  let O = Object(this);
  // 无符号右移保证length是数字
  let len = this.length >>> 0;
  let argCount = items.length >>> 0;
  // js能表示的最大正整数为2 ** 53 - 1
  if (len + argCount > 2 ** 53 - 1) {
    throw new TypeError("数组长度超过最大值");
  }
  // 将传入的值依次传入到原数组中
  for (let i = 0; i < argCount; i++) {
    O[let + i] = items[i];
  }
  // 设置新的length并返回
  let newLength = len + argCount;
  O.length = newLength;
  return newLength;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

Array.prototype.pop

Array.prototype.pop = function () {
  let O = object(this);
  let len = this.length >>> 0;
  // 长度为0的数组直接返回undefined
  if(len === 0) {
    O.length = 0;
  }
  // 删除最后一位元素,修改length值
  len--;
  let value = O[len];
  delete O[len];
  O.length = len;
  // 返回被删除的值
  return value;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Array.prototype.map

Array.prototype.map = function (callbackFn, thisArg) {
  // null和undefined判断
  if (this === null || this === undefined) {
    throw new TypeError("Cannot read property 'map' of null");
  }
  // callbackFn必须为函数
  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 i = 0; i < len; i++) {
    // 判断当前项存在时才执行操作
    if (i in O) {
      let iValue = O[i];
      // map callback的3个参数为当前项,当前索引,以及整个数组
      let mapedValue = callbackFn.call(T, iValue, i, O);
      // 执行结果传入新数组
      A[i] = mapedValue;
    }
  }
  // 返回新数组
  return A;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

Array.prototype.reduce

Array.prototype.reduce = function (callbackFn, initialValue) {
  if (this === null || this === undefined) {
    throw new TypeError("Cannot read property 'reduce' of null");
  }
  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;
      }
    }
    // 未找到有效初始值则抛出错误
    if(accumulator === undefined){
      throw new Error('Each element of the array is empty');
    }
  }
  // 遍历数组执行归并
  for(;k < len; k++) {
    if (k in O) {
      // 归并执行callbackfn,传入的参数为,前一项,当前项和整个数组
      accumulator = callbackfn.call(undefined, accumulator, O[k], O);
    }
  }
  // 返回归并结果
  return accumulator;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36