JavaScript中通常分为两种类型转换,“隐式强制类型转换”(implicit coercion)和“显式强制类型转换”(explicit coercion)。

下面所有代码的源码可以在此处查看

一、强制转换为字符串(ToString)

1)ToString

基本类型值的字符串化规则为:null转换为"null",undefined转换为"undefined",true转换为"true"。数字的字符串化则遵循通用规则,不过那些极小和极大的数字使用指数形式:

  1. // 1.07 连续乘以七个 1000
  2. var a = 1.07 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000;
  3. // 七个1000一共21位数字
  4. console.log(a.toString()); // "1.07e21"

对普通对象来说,除非自行定义,否则toString()(Object.prototype.toString())返回内部属性[[Class]]的值

2)JSON

JSON.stringify(..)在对象中遇到undefined、function和symbol时会自动将其忽略,在数组中则会返回null(以保证单元位置不变)。

如果对象中定义了toJSON()方法,JSON字符串化时会首先调用该方法,然后用它的返回值来进行序列化。

  1. JSON.stringify(undefined); // undefined
  2. JSON.stringify(function() {}); // undefined
  3.  
  4. JSON.stringify(
  5. [1, undefined, function() {}, 4]
  6. ); // "[1,null,null,4]"
  7. JSON.stringify({
  8. a: 2,
  9. b: function() {}
  10. }) // "{"a":2}"

二、强制转换数字(ToNumber)

1)ToNumber

1. true转换为1false转换为0

2. undefined转换为NaNnull转换为0

3. ""[]转换为0。处理失败时返回NaN

4. ToNumber对以0开头的十六进制数并不按十六进制处理

2)对象

对象(包括数组)会首先被转换为相应的基本类型值,如果返回的是非数字的基本类型值,则再遵循以上规则将其强制转换为数字。

为了将值转换为相应的基本类型值,抽象操作ToPrimitive会首先(通过内部操作DefaultValue)检查该值是否有valueOf()方法。

如果有并且返回基本类型值,就使用该值进行强制类型转换。如果没有就使用toString()的返回值(如果存在)来进行强制类型转换。

  1. var a = {
  2. valueOf: function() { //先执行valueOf
  3. return "42";
  4. }
  5. };
  6. var b = {
  7. toString: function() { //再执行toString
  8. return "42";
  9. }
  10. };
  11. var c = [4, 2];
  12. c.toString = function() {
  13. return this.join(""); // "42"
  14. };
  15. Number(a); //
  16. Number(b); //
  17. Number(c); //
  18. Number(""); //
  19. Number([]); //
  20. Number(["abc"]); // NaN

三、强制转换布尔值(ToBoolean)

1)假值(falsy value)

可强制类型转换为false。包括undefinednullfalse+0-0NaN""

  1. undefinednullfalse、+0、-0NaN""

2)真值

[]{}function(){}都不在假值列表中。

  1. []、{}和function(){}

四、显式强制类型转换

1)奇特的~运算符

~x大致等同于-(x+1)

  1. ~42; // -(42+1) ==> -43

用~~来截除数字值的小数部分~~中的第一个~执行ToInt32并反转字位,然后第二个~再进行一次字位反转,即将所有字位反转回原值,最后得到的仍然是ToInt32的结果。

  1. //奇特的~
  2. var a = "Hello World";
  3. if (~a.indexOf("lo")) { //如果未找到就返回-1,(-1+1)=0就是false
  4. // 找到匹配!
  5. }
  6.  
  7. //~~
  8. Math.floor(-49.6); // -50
  9. ~~-49.6; // -49

2)显式解析数字字符串

解析允许字符串中含有非数字字符,解析按从左到右的顺序,如果遇到非数字字符就停止。

转换不允许出现非数字字符,否则会失败并返回NaN。

  1. var a = "42";
  2. var b = "42px";
  3. Number(a); //
  4. parseInt(a); //
  5.  
  6. Number(b); // NaN
  7. parseInt(b); //

解析字符串中的浮点数可以使用 parseFloat(..) 函数。

非字符串参数会首先被强制类型转换为字符串(执行toString方法)。

  1. parseInt(0.000008); // 0 ("0" 来自于 "0.000008")
  2. parseInt(0.0000008); // 8 ("8" 来自于 "8e-7")
  3. parseInt(false, 16); // 250 ("fa" 来自于 "false")
  4. parseInt(parseInt, 16); // 15 ("f" 来自于 "function..")
  5.  
  6. parseInt("0x10"); // 16
  7. parseInt("103", 2); //

五、隐式强制类型

1)字符串和数字之间的隐式强制类型转换

如果+其中一个操作数是字符串则执行字符串拼接;否则执行数字加法。

如果其中一个操作数是对象(包括数组), 则对其调用 ToPrimitive 抽象操作。

  1. var a = "42";
  2. var b = "0";
  3. a + b; // "420" 两个都是字符串
  4. var c = 42;
  5. var d = 0;
  6. c + d; // 42 两个都是数字
  7. var a = [1, 2];
  8. var b = [3, 4];
  9. a + b; // "1,23,4" 两个都是对象

2)隐式强制类型转换为布尔值

以下情况,非布尔值会被隐式强制类型转换为布尔值,遵循ToBoolean 抽 象操作规则。

1. if (..)语句中的条件判断表达式。

2. for ( .. ; .. ; .. )语句中的条件判断表达式(第二个)。

3. while (..)do..while(..)循环中的条件判断表达式。

4. ? :中的条件判断表达式。

5.  逻辑运算符||(逻辑或)和&&(逻辑与)左边的操作数(作为条件判断表达式)。

六、宽松相等和严格相等

常见的误区是“ == 检查值是否相等, === 检查值和类型是否相等”。听起来蛮有道理,然而 还不够准确。

正确的解释是:“ == 允许在相等比较中进行强制类型转换,而 === 不允许

1)字符串和数字之间的相等比较

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

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

2)其他类型和布尔类型之间的相等比较

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

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

3)null 和 undefined 之间的相等比较

1.如果 x 为 null , y 为 undefined ,则结果为 true 。

2.如果 x 为 undefined , y 为 null ,则结果为 true 。

4)对象和非对象之间的相等比较

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

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

  1. var a = "abc";
  2. var b = Object(a); // 和new String( a )一样
  3. a === b; // false
  4. //b 通过 ToPromitive 进行强制类型转换(也称为“拆封”,unboxed或者unwrapped) ,并返回标量基本类型值 "abc" ,与 a 相等。
  5. a == b; // true
  6.  
  7. //null和undefined不能够被封装(boxed),Object(null)和 Object(undefined) 均返回一个常规对象。
  8. var a = null;
  9. var b = Object(a); // 和Object()一样
  10. a == b; // false
  11.  
  12. var c = undefined;
  13. var d = Object(c); // 和Object()一样
  14. c == d; // false
  15. //NaN能够被封装为数字封装对象,但NaN不等于NaN
  16. var e = NaN;
  17. var f = Object(e); // 和new Number( e )一样
  18. e == f; // false

5)假值的相等比较

假值,就是上面ToBoolean中提到的假值。

  1. "0" == false;//true 按照2)和1)的规则
  2. false == 0;//true 按照2)的规则
  3. false == "";//true 按照2)和1)的规则
  4. false == [];//true 按照4)2)1)的规则
  5. "" == 0;//true 按照1)
  6. "" == [];//true 按照4)的规则
  7. 0 == [];//true 按照4)1)的规则
  8. [] == ![]// true ![]执行后的值是false

6)安全运用隐式强制类型转换

1.如果两边的值中有true或者false,千万不要使用==。

2.如果两边的值中有[]、0或者"" ,尽量不要使用==。

7)比较图表

dorey提供的一张在线图表

《你不知道的JavaScript》整理(六)——强制类型转换的更多相关文章

  1. 谈 JavaScript 中的强制类型转换 (2. 应用篇)

    这一部分内容是承接上一篇的, 建议先阅读谈 JavaScript 中的强制类型转换 (1. 基础篇) 前两章讨论了基本数据类型和基本包装类型的关系, 以及两个在类型转换中十分重要的方法: valueO ...

  2. 详细理解javascript中的强制类型转换

    将值从一种类型转换为另一种类型通常称为类型转换,这是显式的情况:隐式的情况称为强制类型转换,JavaScript 中的强制类型转换总是返回标量基本类型值,如字符串.数字和布尔值. 如何理解: 类型转换 ...

  3. 谈 JavaScript 中的强制类型转换 (1. 基础篇)

    1. 从基本包装类型讲起 讨论基本包装类型的前提是了解基本数据类型(也可以称为原始类型, 简单数据类型等).然后通过基本数据类型调用方法的行为, 引出基本包装类型的概念和作用. 1.1 基本数据类型 ...

  4. Javascript基础之-强制类型转换(二)

    思考下面这个问题: console.log(+"123"); // 123 console.log(-"123"); // -123 console.log(+ ...

  5. 你不知道的JavaScript(六)Box&Unbox

    很多语言中都有Box和Unbox的概念,很多书籍把Box翻译为"装箱操作",指的是將基本数据类型包装成对象:Unbox和它相反,把对象类型转换为基本类型. 我们知道JavaScri ...

  6. javascript第六课类型转换

    1.parseint(参数): 转换为整数,即使参数中的字符串包含字母数字混合,此方法也会自动一个一个判断和转换   parseInt(参数,进制);将参数通过几进制的方式转为数字 2.parsefl ...

  7. 你不知道的JavaScript之类型

    JavaScript是一门简单易用的语言,应用广泛,同时它的语言机制又十分复杂和微妙,即使经验丰富的开发人员也需要用心学习才能真正掌握. <你不知道的JavaScript>中是这样定义类型 ...

  8. JS的强制类型转换

    将值从一种类型转换为另一种类型通常称为类型转换,这是显式的情况,隐式的情况称为强制类型转换. JavaScript中的强制类型转换总是返回标量基本类型值,如字符串.数字和布尔值,不会返回对象和函数. ...

  9. javascript中强制类型转换

    javascript开发过程中,强制类型转换一般发生在条件判断和==运算符.其他情况,发生的类型转换(与这两种情况也是基本类似,属于万变不离其宗的范畴),暂不讨论. == 双等运算符 考虑代码: a ...

随机推荐

  1. Java Swing paint repaint update 方法的关系

    Java Swing paint repaint update 方法的关系: 参考:http://blog.csdn.net/xiaoliangmeiny/article/details/691665 ...

  2. table固定前两列和最后一列,其他滑动显示

    网上搜的基本都是4个table做的,数据处理比较麻烦,写了个一个table的,此示例只固定了前两列和最后一列,和网上的不太一样. 网上搜的基本都是4个table做的,数据处理比较麻烦,写了个一个tab ...

  3. jsp+servlet+javaBean+Dao

    一.Servlet程序各模块介绍1.JSP 用于显示.收集数据的部分.2.Servlet 用于验证数据.实例化JavaBean.调用DAO连接数据库.控制页面跳转3.DAO 用于连接数据库及进行数据库 ...

  4. HDU5058

    So easy Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  5. [UWP]依赖属性1:概述

    1. 概述 依赖属性(DependencyProperty)是UWP的核心概念,它是有DependencyObject提供的一种特殊的属性.由于UWP的几乎所有UI元素都是集成于DependencyO ...

  6. 报表学习总结(一)——ASP.NET 水晶报表(Crystal Reports)的简单使用

    一.水晶报表简介 Crystal Reports(水晶报表)是一款商务智能(BI)软件,主要用于设计及产生报表.水晶报表是业内最专业.功能最强的报表系统,它除了强大的报表功能外.最大的优势是实现了与绝 ...

  7. Codeforces Round #396 (Div. 2)

    C. Mahmoud and a Message time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  8. Swift 2.0 字符串学习笔记(建议掌握OC字符串知识的翻阅)

    自己公司开现在使用OC语言在写,但Swift似乎是苹果更推荐使用的开发语言,估计也是未来开发的趋势,自己以前有接触swift,但又由于公司的项目赶,也没有时间去好好地学习这款开发语言.现在年底了,项目 ...

  9. 【读书笔记】-- JavaScript模块

    在JavaScript编程中我们用的很多的一个场景就是写模块.可以看成一个简单的封装或者是一个类库的开始,有哪些形式呢,先来一个简单的模块. 简单模块 var foo = (function() { ...

  10. mdadm命令详解及实验过程

    一.概念 mdadm是multiple devices admin的简称,它是Linux下的一款标准的软件 RAID 管理工具,作者是Neil Brown 二.特点 mdadm能够诊断.监控和收集详细 ...