Bootstrap

由一道题看push方法的实现原理

最近同事分享了一道题

let obj = {
   2:3,
   3:4,
   length:2,
   push:Array.prototype.push
 }
 obj.push(1)
 obj.push(2)
 console.log(obj)

obj是一个类数组,其中引入了Array原型链上的push方法,关键就是要搞清楚Array.prototype.push的方法定义。
经过查看资料,发现push的方法可以用js如下模拟:

Array.prototype.push = function(...items) {

  let O = Object(this);  // ecma 中提到的先转换为对象

  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")

  }

  for(let i = 0; i < argCount; i++) {

    O[len + i] = items[i];

  }

  let newLength = len + argCount;

  O.length = newLength;

  return newLength;

}

push的参数可以是一个元素,或者多个逗号连接的元素。
在这道题中,

obj.push(1)相当于obj[obj.length] = 1,obj.length = obj.length+1;
obj.push(2)相当于obj[obj.length] = 2,obj.length = obj.length+1;

因此最后的结果是

console.log(obj)
{2:1,3:2,length:4,push:fn}

如果改成

let obj = {
   2:3,
   3:4,
   length:2
 }
Array.prototype.push.call(obj,1)
Array.prototype.push.call(obj,2)
console.log(obj)

结果是相同地,使用call将push方法借用给obj对象

;