ECMA规范之Array-prototype-push

1,219 阅读3分钟

我们几乎每天都要用到push方法,我们真的明白在调用push方法后,浏览是怎么运行这个方法?

其中ecma规范第三版(1999)是这样定义的:

  • 1 调用对象的[Get]方法获取参数列表中第一个参数长度
  • 2 将结果用ToUint32方法赋值给n
  • 3 在参数列表中获取下一个参数,如果没有,直接跳到第七步
  • 4 调用对象的[Put]方法将当前参数Tostring,put到当前对象中去
  • 5 n自增1
  • 6 回到第三步,循环
  • 7 调用对象的[Put]方法,将参数长度和n put 到当前对象中去
  • 8 返回n

push原生方法的长度属性为1

到了2011年,我们push规范进行了变更,大致变更如下:

  • 1 调用ToObject处理this对象,将结果赋值给O
  • 2 调用O对象的内部方法[Get]将第一个参数长度赋值给lenVal
  • 3 将ToUint32(lenVal)赋值给n
  • 4 将传递给函数调用的参数从左到右,依次赋值给items
  • 5 如果items不为空,重复下列方法: a.移除items中的第一个元素,并且将移除元素的值赋给E b.调用O对象的[Put]内部方法,在O对象上设置ToString(n),E和true属性。 c.n自增1
  • 6 当items为空时,调用O对象的[Put]内部方法,设置O对象的参数长度,n和true等属性。
  • 7 返回n

NOTE: push方法被刻意设计为一种通用的方法;它并不要求this对象是一个数组对象。因此它能使用特定方法被其他对象调用。

var obj={

    addElem : function addElem(elem){
        
        [].push.call(this,elem);
        //Array.prototype.push.call(this,elem);
    }
}

obj.addElem('1');
obj.addElem('2');
console.log(obj.length) //result is 2

时光回到2015年,ecma规范又一次更新,push当然也是更新了

我们来看看具体有哪些更新:

  • 1 ToObject(this)并且将值赋给O
  • 2 调用ReturnIfAbrupt(O) ps:这个函数是啥意思?目前还没弄懂,弄懂再回来补充
  • 3 将O的长度调用ToLength()赋值给len ps:这个toLength又是什么呢?
  • 4 调用ReturnIfAbrupt(len)
  • 5 步骤还是跟第五版一样,将所有传递进函数的参数从左至右赋值给items。
  • 6 将items中的元素个数赋值给argCount
  • 7 如果len + argCount > 2的53次方减一,抛出TypeError exception
  • 8 如果items不为空,重复下列行为: a.从items移除第一个元素,并且将这个元素的值赋给E b.调用Set方法设置O对象的ToString(len),E和true属性 c.ReturnIfAbrupt(setStatus) d.len自增1
  • 9 如果items为空,调用Set方法,设置O对象"length",len和true属性
  • 10 ReturnIfAbrupt(setStatus).
  • 11 返回len

es6内部抽象程度更高,更加规范,调用了很多方法来处理不同的过程,那让我们来了解研究这些方法到底是干什么的。

ToObject

Object抽象方法它可以将参数转变为对象类型的值。

arguments type result
Completion Record If argument is an abrupt completion, return argument. Otherwise return ToObject(argument.[[value]]).
Undefined Throw a TypeError exception.
Null Throw a TypeError exception.
Boolean 返回新的Boolean对象
Number 返回新的Number对象
String 返回新的String对象
Symbol 返回新的Symbol对象
Object 返回对象

其中Boolean,Number,String,Symbol,参数类型为这些时,返回的新对象都是用internal slot(暂且翻译为内部插槽重新设置的对象),但是何为internal slot,还不理解,理解再来叙说。

ReturnIfAbrupt

完成时 类型被用作记录运行时,值传递的状态,例如一些跳出局部控制的状态(break, continue, return and throw)。

Field Value Meaning
[[type]] One of normal, break, continue, return, or throw 其中某一种状态已经被调用
[[value]] Undefined, Null, Boolean, String, Symbol, Number, and Object中的一种,或者empty 值已经产生
[[target]] any ECMAScript string or empty The target label for directed control transfers.

重点:abrupt completion(突然完成) 是指在[[Type]]之中除了nomral之外的状态