《你不知道的JavaScript》整理(六)——强制类型转换

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

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

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

1)ToString

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

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

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

2)JSON

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

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

JSON.stringify(undefined); // undefined
JSON.stringify(function() {}); // undefined

JSON.stringify(
  [1, undefined, function() {}, 4]
); // "[1,null,null,4]"
JSON.stringify({
    a: 2,
    b: function() {}
}) // "{"a":2}"

二、强制转换数字(ToNumber)

1)ToNumber

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

2. undefined转换为NaNnull转换为0

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

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

2)对象

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

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

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

var a = {
  valueOf: function() { //先执行valueOf
    return "42";
  }
};
var b = {
  toString: function() { //再执行toString
    return "42";
  }
};
var c = [4, 2];
c.toString = function() {
  return this.join(""); // "42"
};
Number(a); // 42
Number(b); // 42
Number(c); // 42
Number(""); // 0
Number([]); // 0
Number(["abc"]); // NaN

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

1)假值(falsy value)

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

undefined、null、false、+0、-0、NaN、""

2)真值

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

[]、{}和function(){}

四、显式强制类型转换

1)奇特的~运算符

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

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

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

//奇特的~
var a = "Hello World";
if (~a.indexOf("lo")) { //如果未找到就返回-1,(-1+1)=0就是false
  // 找到匹配!
}

//~~
Math.floor(-49.6); // -50
~~-49.6; // -49

2)显式解析数字字符串

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

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

var a = "42";
var b = "42px";
Number(a); // 42
parseInt(a); // 42

Number(b); // NaN
parseInt(b); // 42

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

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

parseInt(0.000008); // 0 ("0" 来自于 "0.000008")
parseInt(0.0000008); // 8 ("8" 来自于 "8e-7")
parseInt(false, 16); // 250 ("fa" 来自于 "false")
parseInt(parseInt, 16); // 15 ("f" 来自于 "function..")

parseInt("0x10"); // 16
parseInt("103", 2); // 2

五、隐式强制类型

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

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

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

var a = "42";
var b = "0";
a + b; // "420" 两个都是字符串
var c = 42;
var d = 0;
c + d; // 42 两个都是数字
var a = [1, 2];
var b = [3, 4];
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 的结果。

var a = "abc";
var b = Object(a); // 和new String( a )一样
a === b; // false
//b 通过 ToPromitive 进行强制类型转换(也称为“拆封”,unboxed或者unwrapped) ,并返回标量基本类型值 "abc" ,与 a 相等。
a == b; // true

//null和undefined不能够被封装(boxed),Object(null)和 Object(undefined) 均返回一个常规对象。
var a = null;
var b = Object(a); // 和Object()一样
a == b; // false

var c = undefined;
var d = Object(c); // 和Object()一样
c == d; // false
//NaN能够被封装为数字封装对象,但NaN不等于NaN
var e = NaN;
var f = Object(e); // 和new Number( e )一样
e == f; // false

5)假值的相等比较

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

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

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

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

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

7)比较图表

dorey提供的一张在线图表

时间: 2024-08-06 04:23:29

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

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

将值从一种类型转换为另一种类型通常称为类型转换,这是显式的情况:隐式的情况称为强制类型转换,JavaScript 中的强制类型转换总是返回标量基本类型值,如字符串.数字和布尔值. 如何理解: 类型转换发生在静态类型语言的编译阶段,而强制类型转换则发生在动态类型语言的运行时? 1.如果是静态语言,比如c等,所有的类型转换应该都是在编译阶段处理的吧? 2.如果是动态语言,如js等, 编译阶段会处理类型转换吗? 一.ToString 它负责处理非字符串到字符串的强制类型转换 数字的字符串化遵循通用规则

你不知道的JavaScript之类型

JavaScript是一门简单易用的语言,应用广泛,同时它的语言机制又十分复杂和微妙,即使经验丰富的开发人员也需要用心学习才能真正掌握. <你不知道的JavaScript>中是这样定义类型的: 类型是值的内部特征,它定义了值的行为,以使其区别于其他值. 这样的定义可能略简单了一些,不够已经足够让我们去理解类型的含义. 不得不提的强制类型转换 在JavaScript中,强制类型转换无处不在,在我们的程序中,有意无意地,都经常地利用到强制类型转换.它给我们带来了许多便利,同时也容易造成某一些坑.当

带你玩转JavaScript中的隐式强制类型转换

正题开始前我想先抛出一个问题,==和===有什么区别?可能一般人会想,不就是后者除了比较值相等之外还会比较类型是否相等嘛,有什么好问的,谁不知道?!但是这样说还不够准确,两者的真正区别其实是==在比较的时候允许做强制类型转换,而===不允许.好了终于引出了今天的重点,我们平时肯定遇到过强制类型转换的时候,死活想不通为什么要这样转换(为什么这两个相等)的情况.那么下面我就以==为例,来说明一下其中强制类型转换的规则. 前提知识 JavaScript中的6大类型:undefined.null.boo

JavaScript学习10 JS数据类型、强制类型转换和对象属性

JavaScript学习10 JS数据类型.强制类型转换和对象属性 JavaScript数据类型 JavaScript中有五种原始数据类型:Undefined.Null.Boolean.Number以及String. Undefined数据类型的值只有一个:undefined. 在JavaScript中,如果函数没有声明返回值,那么会返回undefined.(后面有实例). 如果typeof后面跟一个未定义的参数,也是返回undefined. Null数据类型的值只有一个:null. null与

《你不知道的JavaScript》整理(二)——this

最近在读一本进阶的JavaScript的书<你不知道的JavaScript(上卷)>,这次研究了一下“this”. 当一个函数被调用时,会创建一个活动记录(执行上下文). 这个记录会包含函数在哪里被调用(调用栈).函数的调用方法.传入的参数等信息. this就是记录的其中一个属性,会在函数执行的过程中用到. this既不指向函数自身也不指向函数的作用域. this实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用. 一.调用位置 调用位置就在当前正在执行的函数的前一个调用中

《你不知道的JavaScript》整理(一)——作用域、提升与闭包

最近在读一本进阶的JavaScript的书<你不知道的JavaScript(上卷)>,里面分析了很多基础性的概念. 可以更全面深入的理解JavaScript深层面的知识点. 一.函数作用域 1)函数作用域 就是作用域在一个“Function”里,属于这个函数的全部变量都可以在整个函数的范围内使用及复用. function foo(a) { var b = 2; function bar() { // ... } var c = 3; } bar(); // 失败 console.log( a,

C++学习之路(六):关于C++提供的强制类型转换

C语言中提供了旧式的强制类型转换方法.比如: int a  =1; char *p = (char *)&a; 上述将a的地址单元强制转换为char类型的指针.这里暂且不说上述转换结果是否合理,但上述这样的强制类型转换,如果转换过程出现问题,对于问题的追踪与排查也比较困难. 对于C++而言,提供了较为安全的强制类型转换方法,下面进行简单介绍. 一.static_cast 对于任何具有明确定义的类型转换,只要不包含底层const,都可以用static_cast. 主要可以有以下几种转换: (1)用

__x__(53)0918第七天__ JavaScript 强制类型转换

其他进制的数字 二进制    以 0b 开头的 Number 八进制    以 0 开头的 Number 十六进制    以 0x 开头的 Number 注意:无论是多少进制的数字,输出都是十进制 强制类型转换 主要指的是将 变量类型 转换为String,Number,Boolean类型. 1. 转换为字符串 String 通过调用 String.toString() 方法 : Null .Undefined 没有 .toString() 方法,意味着不能用此方法转换 var a = 123;

Js中的假值_ES5中定义的ToBoolean方法强制类型转换后值为false

你不知道的Javascript(中)--ToBoolean javascript中的值可以分为以下两类: 1.可以被强制类型转换为false的值 2.其他(被强制类型转换为true的值) 假值---以下是js的ES规范中定义了的假值: undefined null false +0.-0和NaN ""-空字符串 假值的不二强制类型转换结果为false.一般除假值以外的都是真值. 假值对象--封装了假值的对象 eg: var a=new Boolean(false); var b=new