这一节,应该算是强制类型转换的最后一个小节了,这一部分呢,主要会讲比较操作中遇到的强制类型转换。

抽象相等== 和严格相等 ===。

简单且粗略的来说,抽象相等和严格相等的区别就是抽象相等在比较的时候,如果比较的两个数类型不同,会先进行类型转换再比较,而严格类型呢,比较简单粗暴一些,直接返回false。

当然啦,你也可以这么理解,抽象比较的时候,允许类型转换,而严格相等则不允许,所以看如下例子:

console.log('1111' == 1111)   // true
console.log('1111' === 1111)  // false

这个例子很容易理解,那么本例中,抽象相等中究竟是从字符串转换为数字呢,还是相反?

规范是这么说的:

如果相比较的两个操作数,其中一个是数字类型,另一个是字符串类型的话,那么字符串将会转换为数字,再进行比较,就相等于:

console.log(Number('1111') == 1111);

那么如果是布尔值呢?比如说

console.log("42" == true);  // false
console.log(12 == true);  // false
console.log(-1 == true);   // false

哇哦,都是false呀,是不是和一开始的认知不太一样呢?尤其是对于有其他语言基础的童鞋们。

这一方面ecma规范也有说了:

如果操作数中,有布尔类型的,那么他将会转为数字类型,再进行比较。

大家请看着个例子,应该不用多说了吧,上面说过了,严格相等的话,如果类型不一样,直接返回false,毕竟人家是严格相等,很严格的。

console.log(false === 0); // false
console.log(false == 0); // true

那么如果null和undefined比较呢?

console.log(null == null); // true
console.log(undefined == null); // true
console.log(undefined == undefined) // true

第一个和第三个大家比较容易理解,第二个可能比较疑惑,为甚呢?

因为规范上有说,如果比较的两种,一个是undefined另一种是null,则返回true,但是这个也只是对应于抽象相等,严格相等时不可能相等的。因为类型不一样。

至于上面那个呢,我还应该多说一句,除了undefined和null比较或者是他们同类型的比较是true,和其他任何类型的值比较都是false,有一些看起来像true的,结果都是false,要注意一下。

console.log(null == false); // false
console.log(undefined == 0); // false
console.log(undefined == "") // false

接下来这个比较重要了,就是对象和非对象的比较。

先看规范定义吧:

对于两个操作数,如果其中一个是字符串或数字,另一个是对象的话,那么对象会转为原始值,然后再进行比较。

那么怎么获取原始值呢?

其实其他小节也都讲过,这里在复述一下,简单来说,就是先调用对象的valueOf()函数,如果它不存在,或者不会转为基本类型值,就调用toString()函数,如果toString()不存在或者返回的是非字符串的值,将会直接报错。

看起来有一点枯燥吧,那么看例子。

console.log([2].valueOf());  // [2]
console.log([2].toString());  // "2"
console.log([2].toString() == 2);  // true

数组[2]呢,可以看到,他的valueOf返回的是一个数组,那么他就会用toString(),转为字符串“2”,字符串2和数字2比较呢,根据上面讲的,字符串2会变为数字2,相等,返回true。

在看一个例子

var obj = {valueOf() {return 3;}
}
console.log(obj == 3);  // true
var obj1 = Object.create(null);
console.log(obj1 == 3);  // Uncaught TypeError: Cannot convert object to primitive value

这个呢,就是对象先调用valueOf()得到基本类型值3,然后再进行比较得到true,第二个呢,得到了一个纯净的对象(没有prototype),然后获取不到valueOf()和toString(),直接报错了。

那其他的情况呢

console.log(NaN == NaN);  // false
console.log(NaN === NaN);  // false
console.log(+0 == -0);   // true
console.log(+0 === -0);  // true
console.log({} == {});  // false
console.log({} === {});  // false
var obj1 = obj = {};
console.log(obj == obj1);  // true
console.log(obj === obj1);  // true

这个分析一下,规范中:

NaN不等于自身,+0和-0是相等的,对象是否相等是根据是否引用同一对象。

对象相等的已经介绍完了,那么判断不相等的呢?比如说(!=)和(!==)他们的区别呢

实际上,他们的语法判断规则和相等的规则一样,只不过最后多了一个置反的一个步骤。也就是!(a == b)或者是!(a === b),我感觉应该很容易理解,就不举例了。

那么最后就要讲关系操作符了,也就是大于小于这些的。

那么我们先讲两个操作符中,有至少是一个数字的情况。请看下面的例子

console.log(1 < 2);  // true
console.log("0b1" < 2);  // true
var obj = {valueOf() {return 1;}
}
console.log(obj < 2);   // true
console.log(1 < Infinity);  // true
console.log(-Infinity < 1);  // true
console.log(NaN > 1);  // false
console.log(NaN < 1);  // false

上面这几个例子,几乎涵盖了规范中至少有一个操作数是数字的比较的情况。

首先,也是如果有对象的话,会把对象转为基本类型值,在进行比较。

并且如果另一个操作数是字符串的话,会把字符串转成数字。

还有就是数字一直小于正无穷,大于负无穷。

NaN无论怎么判断都是false。

那么如果是字符串之间的比较呢,也就是俩操作数都是字符串的情况。

console.log("1003" > "2"); // false
1
嗯,很简单是吧,如果俩都是字符串的话,实际上会按照字母顺序去比,这样去排出哪个值。

那么是怎么按照字母顺序比的呢,字母顺序又是通过什么方式取得的呢?请看例子:

console.log("aaa" > "aa"); // true
console.log("1003" > "2");  // false
console.log("a" > "b");  // false
console.log('&' < "a");  // true
console.log("A" < "a");  // true
console.log("a".charCodeAt());  // 97
console.log("b".charCodeAt());  // 98
console.log("&".charCodeAt());  // 38
console.log("A".charCodeAt());  // 65

这个例子,应该就很容易理解了,实际上取的是字符串的charCodeAt(),实际上你依然可以理解为转换成数字去比了,只不过字符串的比和含有数字的比是不一样的,数字的比意味着他们整体数字的值的大小去比,而字符串是比从一开始的前缀挨个比每个字母的大小。

是不是依然比较好理解,那么在来一个例子。

var a = [ 42 ];
var b = "043";
console.log(a < b);  // false
console.log(Number(a) < Number(b)); // true

这个结合上面那个规则,自己分析下。

最后的最后,我们看一个你可能略感疑惑的例子:

var a = { b: 42 };
var b = { b: 43 };
console.log(a < b);  // false
console.log(a == b); // false
console.log(a > b);  // false
console.log(a <= b);  // true
console.log(a >= b);  // true

这个例子,确实不太付合常识呀,但是呢,这确实是存在的,我给解释一下。

首先呢,a < b和a > b,由于他们俩都是对象,所以转换为基本类型值后为字符串“[object Object]”,所以返回false,而a == b呢,则是因为他俩并不是同一个对象的不同的引用,所以返回false。

最后俩呢,实际上大于等于或者小于等于可以理解为大于或者小于的值的反值,也就是: !(a <= b),所以前面为false,反一下为true

好啦,三个小章基本把强制类型转换整个梳理了一遍,因为这一块的细节太多,所以说呢,我反倒是建议读到我这里的小伙伴,先把大体规则了解以后,特别细节的规则,用到的时候看看我的小散文,或者直接去看ecma262标准文档也行,但是呢,强调一点就是,假如真的要用之前,还是建议自己吧代码跑一下,这样我的感触就是要比只看效果好太多。

总之感谢大家收看我的小散文。

参考书籍《你不知道的Javascript中卷》

参考文档:ECMAScript 5.1(ECMA-262)

https://www.ecma-international.org/ecma-262/5.1/

本文转载自http://www.lht.ren/article/7/

Javascript基础之-强制类型转换(三) 1相关推荐

  1. Javascript基础之-强制类型转换(三)

    这一节,应该算是强制类型转换的最后一个小节了,这一部分呢,主要会讲比较操作中遇到的强制类型转换. 抽象相等(==)和严格相等(===). 简单且粗略的来说,抽象相等和严格相等的区别就是抽象相等在比较的 ...

  2. Javascript基础之-强制类型转换(一)

    转换为字符串规则如下图代码: console.log(String(undefined)); // "undefined" console.log(String(null)); / ...

  3. JavaScript 强制类型转换三(Boolean)

    (1)number转Boolean var a=123;         a=Boolean(a); 22:43:20.644 boolean at 强制类型转换.html:15 22:43:20.6 ...

  4. JavaScript 中的强制类型转换

    JavaScript 作为一个动态编程语言,其中的数据类型会随着程序运行而动态改变.对于很多人来说,强制类型转换很容易造成程序出错,而要记住所有的转换方式又是一件不那么容易的事情.比如下面这张 Jav ...

  5. JS基础之强制类型转换

    类型转换主要指,将其他数据类型转换为(String.Number.Boolean) 转换为string: 方式一:调用xxx的yyy()方法,就是xxx.yyy() var a=123; a.toSt ...

  6. C语言基础:强制类型转换

    1. 强制类型转换 强制类型转换是把变量从一种类型转换为另一种数据类型. 语法: (type_name) expression 实例:使用强制类型转换运算符把一个整数变量除以另一个整数变量,得到一个浮 ...

  7. js基础_强制类型转换

    任何其他数据类型除了和字符串做相加操作外,与数字类型做算数运算的时候,其他数据类型都会自动转换成数字. 布尔值: true=>1 false=>0 特殊数据类型中: null=>0 ...

  8. Javascript基础系列之(三)数据类型 (数值 Number)

    javascript中想限定一个数的数值,无需限定它是整数还是浮点数型 var num1 = 80 ;var num2 = 55.51;var num3 = -34;var num4 = 9e5;do ...

  9. C++基础回顾-强制类型转换

    直接上代码 float a = 1.0f; cout << (int)a << endl; cout << (int&)a << endl; c ...

  10. JavaScript基础学习之运算符(三)

    运算符也叫操作符       通过运算符对一个或多个值进行运算,并获取运算结果     比如:typeof就是运算符,可以将运算符结果以字符串形式返回     算术运算符       对非Number ...

最新文章

  1. Struts2笔记——result结果类型
  2. 如何使用Navicat恢复数据库脚本
  3. 大批机器人上岗,会影响工作吗,为何我们必须发展人工智能?
  4. hibernate 数据处理
  5. aelf帮助C#工程师10分钟零门槛搭建DAPP私有链开发环境
  6. 179. 最大数---LeetCode---JAVA
  7. android 根据资源名称,如何在Android中按名称访问可绘制资源
  8. PAT1103 Integer Factorization (30)(DFS:回溯)
  9. ASP.NET MVC应用程序把文字写在图片上
  10. 关于网站主页的界面设计不同风格的探索
  11. oracle的服務監聽器,Oracle监听器和服务名的配置
  12. Spring+Spring Boot+Mybatis框架注解解析
  13. hibernate的环境搭建
  14. C语言atoi()函数:将字符串转换成int(整数)
  15. 金融行业灾备压力大?看中和农信如何从容应对
  16. redis - 00 在centos安装
  17. GitHub上10个有趣的开源小游戏(附加在线演示)
  18. 软件开发团队中各个成员的英文简称
  19. 仓库盘点作业流程仓库盘点步骤使用汉码盘点机进行盘点方法
  20. electron 获取电脑mac地址遇到的坑

热门文章

  1. linux下配置Tilera MDE4.1.8方法
  2. REmap发布,用R绘制百度迁徙图
  3. 原创科幻短篇《霾星》
  4. 天津科技大学计算机二级报名,2018年9月天津计算机二级报名6月20-25日
  5. CSDN使用MD编辑器写博客如何让图片居中(调整图片位置大小)MD编辑器学习笔记
  6. 数据结构分类之什么是线性结构、非线性结构
  7. 新西兰的中国新移民现状:缺乏安全感和归属感
  8. SVN报错Skipped ‘xxxController.class.php‘ -- Node remains in conflict
  9. python神经网络编程 代码,python神经网络编程 豆瓣
  10. 计算机怎么放映文档,如何从Apple TV上的计算机播放视频文件