Javascript引擎内部的三种抽象操作

作者: 萧潇在jianshu | 来源:发表于2017-06-24 19:08 被阅读51次

很久之前我在知乎上问过一道很无聊的Js题目,链接在这里JS中{}+[]和[]+{}的返回值情况是怎样的?,这篇文章要说的和这个题目有一些关系。下面介绍一下Js引擎内部的三种抽象操作。

1.通过ToPrimitive()将值转换为原始值。
JavaScript引擎内部的抽象操作ToPrimitive()有着这样的签名:
ToPrimitive(input, PreferredType)

可选参数PreferredType可以是Number或者String,它只代表了一个转换的偏好,转换结果不一定必须是这个参数所指的类型,但转换结果一定是一个原始值.如果PreferredType被标志为Number,则会进行下面的操作来转换输入的值:

①如果输入的值已经是个原始值,则直接返回它.否则,如果输入的值是一个对象.则调用该对象的valueOf()方法.如果valueOf()方法的返回值是一个原始值,则返回这个原始值.否则,调用这个对象的toString()方法.如果toString()方法的返回值是一个原始值,则返回这个原始值.否则,抛出TypeError异常.

②如果PreferredType被标志为String,则转换操作的第二步和第三步的顺序会调换.如果没有PreferredType这个参数,则PreferredType的值会按照这样的规则来自动设置:Date类型的对象会被设置为String,其它类型的值会被设置为Number.

2.通过ToNumber()将值转换为数字
下面的表格解释了ToNumber()是如何将原始值转换成数字的

ToNumber()转换规则

如果输入的值是一个对象,则会首先会调用ToPrimitive(obj, Number)将该对象转换为原始值,然后在调用ToNumber()将这个原始值转换为数字.转型函数Number()会根据此规则执行

3.通过ToString()将值转换为字符串
下面的表格解释了ToString()是如何将原始值转换成字符串

ToString()转换规则

如果输入的值是一个对象,则会首先会调用ToPrimitive(obj, String)将该对象转换为原始值,然后再调用ToString()将这个原始值转换为字符串.转型函数String()会根据该规则执行

理解了Javascript引擎内部的三种抽象操作之后可以看下面的例子:

小例子

这里的转型函数Number会根据2的规定来执行类型转换,由于重写了对象的valueOf和toString函数(之前toString会返回"[object Object]",valueOf会返回该对象),所以Number()根据规则首先调用对象的valueOf方法,没有获得原始值,继续调用toString方法,任然没有获得原始值,这时就会抛出TypeError。

再来看一个例子:即{}+[]和[]+{}的返回值是怎么样?
对于{}+[] 我们将{}理解为一个空的代码块,所以问题就变成了 +[] 的结果,这里的加号并不是代表加法的二元运算符,而是一个一元运算符,作用是将它后面的操作数转换成数字,和Number()函数作用完全一样,即求Number([])的结果是多少?[]继承自Array,Array对象的的valueOf方法直接返回该数组并不是原始值,继续调用toString方法,得到""即一个空的字符串。那么Number("")的结果就是0,所以{}+[]的结果就是0。而[]+{}的结果呢?你可以参考《Javascript高级程序设计》的3.5.5加性操作符一章和本文的相关说明获得答案是"[object Object]"。

文章的最后总结一些类型分别调用valueOf、toString和toLocaleString得到的结果:


相关总结

相关文章

  • Javascript引擎内部的三种抽象操作

    很久之前我在知乎上问过一道很无聊的Js题目,链接在这里JS中{}+[]和[]+{}的返回值情况是怎样的?,这篇文章...

  • ES6学习-12.代理(Proxy)和反射(Reflection

    一、代理和反射 代理可以拦截JavaScript引擎内部目标的底层对象操作,这些底层操作被拦截后会触发响应特定操作...

  • javascript链式操作

    javascript链式操作 最早的js引擎写法

  • 【JS第18期】属性类型详解

    属性类型为了实现javascript 引擎用的,因此在javascript中不能访问它们。为了表示特性是内部值,规...

  • JavaScript宏观任务和微观任务

    在ES3 或者 更早的版本中,JavaScript并无异步操作,所以代码给到JavaScript引擎,它就直接顺次...

  • Java学习——day 05

    主要内容 抽象类 接口 内部类 数组 三种字符声明方式 笔记详情 1. 抽象类 抽象类是一种模板模式,抽象类为子类...

  • Promise里的代码为什么比setTimeout先执行?

    因为Promise产生的是JavaScript引擎内部的微任务,而setTimeout是浏览器API,它产生宏任务...

  • 2017.9.11

    JavaScript内置对象 JS中,可以将对象分为“内部对象”、“宿主对象”和“自定义对象”三种。1,内部对象j...

  • DOM的优化

    DOM的优化 由于解释JavaScript的引擎和解释DOM的引擎是相互独立的,从而导致DOM操作天生就很慢(为什...

  • SICP-14-2.3

    高阶操作,将一些类似的方法进行抽象,通过参数区分方法内部不同的处理通过不断得抽象方法和数据,能将不同操作精简为只需...

网友评论

    本文标题:Javascript引擎内部的三种抽象操作

    本文链接:https://www.haomeiwen.com/subject/eobkcxtx.html