资讯专栏INFORMATION COLUMN

从两个小例子看js中的隐式类型转换

liukai90 / 2717人阅读

摘要:来看代码上面的代码不难理解变量是通过构造函数创建的对象,变量就是一个很简单的数值。一开始,因为是通过构造函数创建的对象,所以值为然后每一次在执行的时候,会调用一次的方法。

废话不多说,我们先来看第一个例子吧。
某天,我遇到了这样一个问题:给出变量a和b的定义,使下面三个语句的输出结果都为true。

console.log(ab);

看到题目的我第一反应是懵逼的,还有这样的操作???然后一开始的思路是往各种神奇的值上面找,比如undefined,null,NaN,“”这样的值,自然是没有得到想要的结果了。
但事实上,真的存在。来看代码:

function A(){
    this.a = 1;
}

A.prototype = {
    toString: function(){
        return this.a += 2;
    }
}

var a = new A();
var b = 5;
console.log(a < b);
console.log(a == b);
console.log(a > b);

上面的代码不难理解:变量a是通过构造函数A创建的对象,变量b就是一个很简单的数值。一开始,因为a是通过构造函数A创建的对象,所以值为1.然后每一次在执行 console.log()的时候,会调用一次A的toString方法。所以,在第一个console.log()的时候,a的值变成了3,而b的值是5,所以atrue;第二个console.log()的时候,a的值变成了5,而b的值还是5,所以a=btrue;第三个console.log()的时候,a的值变成了7,而b的值依旧是5,所以a>btrue
经过上面的分析,我们似乎打开了一个新世界的大门,这里涉及到一个比较重要的概念:隐式类型转换。在上面的例子里,a和b是两个完全不一样的类型,但是它们进行了比较,还得出了结果,这就说明有一个类型在比较的过程中转换成了另一个类型。
这里需要提到一些规范来帮助我们更好的理解。
(小于大于的比较规则和相等是一样的。)
对于字符串和数字来说,ES5规范11.9.3.4.5这样规定:

(1)如果Type(x)是数字,Type(y)是字符串,则返回x == ToNumber(y)的结果
(2)如果Type(x)是字符串,Type(y)是数字,则返回ToNumber(x) == y的结果

对于其他类型和布尔类型的比较,规范11.9.3.6.7这样规定:

(1)如果Type(x)是布尔类型,则返回ToNumber(x) == y的结果
(2)如果Type(y)是布尔类型,则返回x == ToNumber(y)的结果

对于null和undefined来说,ES5规范11.9.3.2.3这样规定:

(1)如果x为null,y为undefined,则结果为x == y
(2)如果x为undefined,y为null,则结果为x == y

也就是说,null和undefined是相等的。
对于对象和非对象来说,ES5规范11.9.3.8.9这样规定:

(1)如果Type(x)是字符串或数字,Type(y)是对象,则返回x == ToPrimitive(y)的结果
(2)如果Type(x)是对象,Type(y)是字符串或数字,则返回ToPrimitive(x) == y的结果

基本就是上面这几种常见的类型的比较了。然后出现了一个我们好像不太常见的东西:ToPrimitive()这个方法。我们来简单了解一下:
对象(或者数组)再进行比较或者类型转换的时候,先会被转换为相应的基本类型值,然后再根据需要进行转换。再转换为基本类型值的时候,抽象操作ToPrimitive会先检查该值是否拥有valueOf()方法。如果有且返回基本类型值,就使用该值作为基本类型值,如果没有就使用toString()方法的返回值作为基本类型值。
上面例子中的相等操作我们使用了==,而不是===。对于这二者的区别,我们经常听到的是,==是不严格相等,只要值相等即可,而===是严格相等,必须值和类型都相等才可以。对于==来说,类型不重要,也就是说在这个过程中是包含了类型转换的。所以,在YouDontKnowJS这本书中,给出的正确解释是:

==允许在相等比较总进行强制类型转换,而===不允许。

然后我们再来看第二个例子吧
题目是这样的:[1]+[2]-[3]=?
这次打算先分析再给出答案,顺便大家也可以自己想想结果是什么。
首先我们看到加减运算符左右两边的值都是数组,那前面提到过对于数组的处理。因为数组的valueOf()操作无法得到简单的基本类型值,所以会调用toString(),这样的话上面那个式子就变成了"1"+"2"-"3"=?。现在这个式子相信大家都比较熟悉了,不过不知道会不会有人一时头脑发热,把答案想成了0。
然后我们继续往下,因为是加减操作符,所以我们从左至右开始计算,"1"+"2"这个结果到底是3还是12呢。那就记住简单的一句话:如果有一个值是字符串,那么就进行字符串拼接,否则进行数字加法。那么很明显,这里是2个字符串,进行字符串拼接,得到"12"
好了,到目前为止,式子已经变成了"12"-"3"了,这应该已经很明显了吧,字符串拼接是肯定不可能的,那就是进行数字运算了,那就是最简单的12-3了,所以最终结果就是9。
其实这个例子里的通过加减运算符进行隐式类型转换在我们日常代码中经常出现,只是可能大家没有特别关注,比如a + ""是把a转换为字符串;a - 0是把a转换为数字。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/107690.html

相关文章

  • ++[[]][+[]]+[+[]]==10? 深入浅出弱类型 JS隐式转换

    摘要:与此相对,强类型语言的类型之间不一定有隐式转换。三为什么是弱类型弱类型相对于强类型来说类型检查更不严格,比如说允许变量类型的隐式转换,允许强制类型转换等等。在中,加性运算符有大量的特殊行为。 从++[[]][+[]]+[+[]]==10?深入浅出弱类型JS的隐式转换 本文纯属原创? 如有雷同? 纯属抄袭? 不甚荣幸! 欢迎转载! 原文收录在【我的GitHub博客】,觉得本文写的不算烂的...

    miya 评论0 收藏0
  • JavaScript 中的隐式类型转换

    摘要:虽然你可能很惊讶甚至可能怀疑是的但是这都是有语言自己的一个隐式类型转换的套路。基本的隐式类型转换基本类型的隐式转换这个其实我们使用的最多例如结果返回的是而不是这就是类型的隐式转换。 基本上所有的语言都有 隐式类型转换 ,但是对于 弱类型语言(JS) 来说 ,隐式类型转换会比 强类型语言(Java) 带来更大的副作用,有些行为甚至是不可思议的。虽然你可能很惊讶 ,甚至可能怀疑是 JS 的...

    txgcwm 评论0 收藏0
  • 掌握 Javascript 类型转换隐式转换救救孩子

    摘要:看下面的代码和会对操作数执行条件判断,如果操作数不是布尔值,会先执行类型转换后再执行条件判断。大家记住这个规则布尔值如果与其他类型进行抽象比较,会先用将布尔值转换为数字再比较。 在上一篇中我们聊过了 JS 类型转换的规则和我发现的一些常见书籍中关于类型转换的一些小错误,当碰到显示类型转换的时候大家可以按照这些规则去拆解出答案。但 JS 中存在一些很隐晦的隐式类型转换,这一篇就来谈下我对...

    weapon 评论0 收藏0
  • 简单说 通过JS隐式转换,关键时刻救你一命

    摘要:说明在比较的时候,会进行隐式转换,你如果对隐式转换不是特别熟悉,结果往往出乎你的意料。解释相信我,这行代码是简单的,它并不复杂,我们先来分解一下这行代码我们把这一行,分解成了行了。简单说中的与方法简单说与引发的思考 说明 JavaScript在比较的时候,会进行隐式转换,你如果对隐式转换不是特别熟悉,结果往往出乎你的意料。 我们来看看这行代码 (![]+[])[+!![]- -+!!...

    fuyi501 评论0 收藏0
  • 简单说 通过JS隐式转换,关键时刻救你一命

    摘要:说明在比较的时候,会进行隐式转换,你如果对隐式转换不是特别熟悉,结果往往出乎你的意料。解释相信我,这行代码是简单的,它并不复杂,我们先来分解一下这行代码我们把这一行,分解成了行了。简单说中的与方法简单说与引发的思考 说明 JavaScript在比较的时候,会进行隐式转换,你如果对隐式转换不是特别熟悉,结果往往出乎你的意料。 我们来看看这行代码 (![]+[])[+!![]- -+!!...

    geekidentity 评论0 收藏0

发表评论

0条评论

liukai90

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<