var a = "42";
var b = "42px";
Number( a ); // 42
parseInt( a ); // 42
Number( b ); // NaN
parseInt( b ); // 42
显式转换为布尔值
var a = "0";
var b = [];
var c = {};
var d = "";
var e = 0;
var f = null;
var g;
Boolean( a ); // true
Boolean( b ); // true
Boolean( c ); // true
Boolean( d ); // false
Boolean( e ); // false
Boolean( f ); // false
Boolean( g ); // false
function onlyOne() {
var sum = 0;
for (var i=0; i < arguments.length; i++) { // 跳过假值,和处理0一样,但是避免了NaN if (arguments[i]) {
sum += arguments[i];
}
}
return sum == 1;
}
var a = true;
var b = false;
onlyOne( b, a ); // true
onlyOne( b, a, b, b, b ); // true
onlyOne( b, b ); // false
onlyOne( b, a, b, b, b, a ); // false
//通过sum += arguments[i]中的隐式强制类型转换,将真值(true/truthy)转换为1并进行 累加。如果有且仅有一个参数为 true,则结果为 1;否则不等于 1,sum == 1 条件不成立。
隐式强制类型转换为布尔值
var a = 42;
var b = "abc";
var c;
var d = null;
if (a) {
console.log( "yep" );
}
// yep
while (c) {
console.log( "nope, never runs" );
}
c = d ? a : b; c;
if ((a && d) || c) {
console.log( "yep" );
}
//非布尔值会被隐式强制类型转换为布尔值以便执行条件判断
|| 和 &&
&& 和 || 运算符的返回值并不一定是布尔类型,而是两个操作数其中一个的值
function foo(a,b) {
a = a || "hello";
b = b || "world";
console.log( a + " " + b );
}
foo(); // "hello world"
foo( "yeah", "yeah!" ); // "yeah yeah!"
function foo() {
console.log( a );
}
var a = 42;
a && foo(); // 42
(1) 如果 x 为 null,y 为 undefined,则结果为 true。
(2) 如果 x 为 undefined,y 为 null,则结果为 true。
对象和非对象之间的相等比较
var a = 42;
var b = [ 42 ];
a == b; // true( 42==42)
(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
a==b //true
var a = null;
var b = Object( a );// 和Object()一样
a == b; //false
var c = undefined;
var d = Object( c );// 和Object()一样
c == d; // false
var e = NaN;
var f = Object( e ); // 和new Number( e )一样
e == f; // false
var a = { b: 42 };
var b = { b: 43 };
a < b; // false
a == b; // false //对象判断引用是不是一致
a > b; // false
a <= b; // true
a >= b; // true
// JavaScript 中 <= 是
“不大于”的意思(即 !(a > b),处理为 !(b < a))。同理 a >= b 处理为 b <= a。
ToPrimitive 转化为原始数据类型 为了将值转换为相应的基本类型值,抽象操作 ToPrimitive 会首先 (通过内部操作 DefaultValue) 检查该值是否有 valueOf() 方法。 如果有并且返回基本类型值,就使用该值进行强制类型转换。如果没有就使用 toString()的返回值(如果存在)来进行强制类型转换。 如果 valueOf() 和 toString() 均不返回基本类型值,会产生 TypeError 错误。
toString()
负责非字符串到字符串的强制类型转换 null 转换为‘null’, undefined 转换成‘undefined’ true 转换成‘true’ false转换成‘false’ 1转换成‘1’, 对象 默认转换成[object Object]。 Array的默认toString()经历过重新定义,讲所有单元字符串化以后再用‘,’连接起来。 将对象强制类型转换为 string 是通过 ToPrimitive 抽象操作来完成的。
JSON.stringify(...) JSON 字符串化和 toString() 的效果基本相同,只不过序列化的结果总是字符串 JSON.stringify(..) 在对象中遇到 undefined、function 和 symbol 时会自动将其忽略,在 数组中则会返回 null(以保证单元位置不变)。 对包含循环引用的对象执行 JSON.stringify(..) 会出错
如果传递给 JSON.stringify(..) 的对象中定义了 toJSON() 方法,那么该方法会在字符 串化前调用,以便将对象转换为安全的 JSON 值。
ToNumber(...) true 转换成1 false 转换成0, undefined 转换为NaN, null 转换为 0
ToNumber 对字符串的处理基本遵循数字常量的相关规则 / 语法,处理失败返回NaN ToNumber 对以 0 开头的 十六进制数并不按十六进制处理,默认 按十进制 对象(包括数组)会首先被转换为相应的基本类型值,如果返回的是非数字的基本类型值,则再遵循以上规则将其强制转换为数字。
ToBoolean 在 JavaScript 中布尔值和数字是不一样的。虽然我们可以将 1 强制类型转换为 true, 将 0 强制类型转换为 false,反之亦然,但它们并不是一回事。 假值 • undefined • null • false • +0、-0 和 NaN • "" 假值的布尔强制类型转换结果为 false。
所有的对象都是真值, new Boolean( false ) //true new Number( 0 ) //true new String( "" ) //true
虽然 JavaScript 代码中会出现假值对象,但它实际上并不属于 JavaScript 语言的范畴。 假值对象看起来和普通对象并无二致(都有属性,等等),但将它们强制类型转换为布尔值时结果为 false。
真值 真值就是假值列表之外的值 掌握真 / 假值的重点在于理解布尔强制类型转换(显式和隐式)
显式强制类型转换 字符串和数字之间的显式转换
String(..) 遵循前面讲过的 ToString 规则,将值转换为字符串基本类型。Number(..) 遵循 前面讲过的 ToNumber 规则,将值转换为数字基本类型。
显式解析数字字符串
解析允许字符串中含有非数字字符,解析按从左到右的顺序,如果遇到非数字字符就停 止。而转换不允许出现非数字字符,否则会失败并返回 NaN。 parseInt(..) 针对的是字符串值,非字符串参数会首先被强制类型转换为字符串
显式转换为布尔值
var a = "0"; var b = []; var c = {}; var d = ""; var e = 0; var f = null; var g; Boolean( a ); // true Boolean( b ); // true Boolean( c ); // true Boolean( d ); // false Boolean( e ); // false Boolean( f ); // false Boolean( g ); // false
一元运算符 ! 显式地将值强制类型转换为布尔值。但是它同时还将 真值反转为假值(或者将假值反转为真值)。所以显式强制类型转换为布尔值最常用的方法是 !!,因为第二个 ! 会将结果反转回原值 在 if(..).. 这样的布尔值上下文中,如果没有使用 Boolean(..) 和 !!,就会自动隐式地进 行 ToBoolean 转换。
隐式强制类型转换 字符串和数字之间的隐式强制类型转换
如果 + 的其中一个操作数是字符串(或者通过valueOf() toString()可以得到字符串), 则执行字符串拼接;否则执行数字加法。 注意坑点 [] + {} //"[object Object]" {} + [] //0
a + ""(隐式)和前面的String(a)(显式)之间有一个细微的差别需要注意。根据 ToPrimitive抽象操作规则,a + ""会对a调用valueOf()方法,然后通过ToString抽象 操作将返回值转换为字符串。而 String(a) 则是直接调用 ToString()。
//-是数字减法运算符,因此a - 0会将a强制类型转换为数字。也可以使用a * 1和a /1,因为这两个运算符也只适用于数字。
布尔值到数字的隐式强制类型转换
隐式强制类型转换为布尔值
|| 和 && && 和 || 运算符的返回值并不一定是布尔类型,而是两个操作数其中一个的值
符号的强制类型转换
符号不能够被强制类型转换为数字(显式和隐式都会产生错误), 但可以被强制类型转换为布尔值(显式和隐式结果都是 true)。
宽松相等和严格相等 == 允许在相等比较中进行强制类型转换,而 === 不允许。
抽象相等 es规则
如果两个值的类型相同,就仅比较它们是否相等 注意以下类外情况 NaN ==NaN //false -0 ==0 //true
两个对象指向同一个值时即视为相等,不发生强制类型转换。 实际上在比较两个对象的时 候,== 和 === 的工作原理是一样的。
字符串和数字之间的相等比较
(1) 如果 Type(x) 是数字,Type(y) 是字符串,则返回 x == ToNumber(y) 的结果。 (2) 如果 Type(x) 是字符串,Type(y) 是数字,则返回 ToNumber(x) == y 的结果。
其他类型和布尔类型之间的相等比较
== 最容易出错的一个地方是 true 和 false 与其他类型之间的相等比较,不涉及 ToBoolean
var a = "42"; var b = true; a == b; // false( 42==1) //这里并不涉及 ToBoolean,所以 "42" 是真值还是假值与 == 本身没有关系! (1) 如果 Type(x) 是布尔类型,则返回 ToNumber(x) == y 的结果; (2) 如果 Type(y) 是布尔类型,则返回 x == ToNumber(y) 的结果。
无论什么情况下都不要使用 == true 和 == false 这里说的只是==,=== true和=== false不允许强制类型转换,所以并不涉及 ToNumber。
null 和 undefined 之间的相等比较
(1) 如果 x 为 null,y 为 undefined,则结果为 true。 (2) 如果 x 为 undefined,y 为 null,则结果为 true。
对象和非对象之间的相等比较
var a = 42; var b = [ 42 ]; a == b; // true( 42==42)
(1) 如果 Type(x) 是字符串或数字,Type(y) 是对象,则返回 x == ToPrimitive(y) 的结果; (2) 如果 Type(x) 是对象,Type(y) 是字符串或数字,则返回 ToPromitive(x) == y 的结果。 这里只提到了字符串和数字,没有布尔值。 布尔值会先被强制类型转换为数字。
比较少见的情况 1 返回其他数字 Number.prototype.valueOf = function() { return 3; }; new Number( 2 ) == 3; // true
2 假值的相等比较
安全运用隐式强制类型转换 1 如果两边的值中有 true 或者 false,千万不要使用 ==。 2 如果两边的值中有 []、"" 或者 0,尽量不要使用 ==。 这时最好用 === 来避免不经意的强制类型转换
抽象关系比较
如果比较双方都是字符串,则按字母顺序来进行比较。
如果不是字符串,比较双方首先调用 ToPrimitive,如果结果出现非字符串,就根据 ToNumber 规则将双方强制类型转换为数字来进行比较。