持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情
强制转换
1. 隐含强制转换/明确强制转换
var a = 42;
var b = a + ""; // 隐含强制转换
var c = String( a ); // 明确强制转换
2. 抽象操作
2.0 ToPrimitive (转为原始值)
规范:
ToPrimitive:tc39.es/ecma262/#se…
参考:
zh.javascript.info/object-topr…
这里有三种类型(hint):
"string"(对于alert和其他需要字符串的操作)"number"(对于数学运算)"default"(少数运算符,以和"number"相同的方式实现转换,除非指定toPrimitive方法)
defalut: 如+和== number和string都适用
转换过程:
- 非Object类型(Number、Symbol等) 不转换
- 调用
obj[Symbol.toPrimitive](hint)如果这个方法存在 (覆盖的话 必须返回基本类型) - 否则,如果 hint 是 "string"
- 尝试
obj.toString()和obj.valueOf(),拿到基本类型值。
- 尝试
- 否则,如果 hint 是 "number" 或者 "default"
- 尝试
obj.valueOf()和obj.toString(),拿到基本类型值。
- 尝试
- 否则,如果 hint 是"default"
- 如果是Date 对象,按照hint=string处理
- 如果是其他对象,按照hint=number处理
- 拿不到基本类型值
- Throw a TypeError exception
2.0.1 string例子
var a = { valueOf () { return 1 } }
String(a) // '[object Object]'
var a = { toString () { return 1 } }
String(a) // '1'
var a = {
valueOf () { return 1 },
toString () { return 2 }
}
String(a) // '2'
2.0.2 number/defualt例子
var a = {
valueOf () { return 1 },
toString () { return 2 }
}
Number(a) // 1 number
a + '' // '1' default
额
{}放前面写,被当成空代码块了,返回的是+''的值
{} + '' // 0
'' + {} // [object Object]
2.1 ToString
2.1.1 基本类型
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(1) // '1'
String(1.07 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000) // "1.07e21"
2.1.2 对象
一个对象被强制转换为一个 string 要通过 ToPrimitive 抽象操作。参见ToPrimitive
262.ecma-international.org/5.1/#sec-8.…
2.2 ToNumber
任何非
number值,以一种要求它是number的方式被使用,比如数学操作,就会发生ToNumber抽象操作。
2.2.1 基本类型
// 常规
Number(undefined) // NaN
Number(false) // 0
Number('') // 0
Number('0xa') // 10 十六进制
Number('0o123') // 83 八进制
// 特别
Number('0123') // 123 0开头的八进制会被当做十进制转换
Number(Symbol(1)) // 报错
Number(10n) // 10 ?报错?
2.2.2 对象
一个对象被强制转换为一个 number 要通过 ToPrimitive 抽象操作 , 参见ToPrimitive
262.ecma-international.org/5.1/#sec-8.…
Number( [] ); // 0 过程,valueOf返回[]不是基本类型,调用toString返回'' 空字符串最后转成0
Number( [ "abc" ] ); // NaN
Number( {} ); // NaN 过程,valueOf返回{}不是基本类型,toString返回'[object Object]',转成NaN
// 特别
Number( null ) // 0
2.3 ToBoolean
2.3.1 Falsy 值
被强制转换为 boolean,将成为 false 的值
任何没有明确地存在于 falsy 列表中的东西,都是 truthy。
所有Falsy值:
undefinednullfalse+0,-0, andNaN""
2.3.2 Falsy 对象
这几个是普通对象
var a = new Boolean( false );
var b = new Number( 0 );
var c = new String( "" );
var d = Boolean( a && b && c );
d; // true
Falsy对象
// 历史原因,document.all用来判断是否为老版本ie, if(document.all) {老ie},也就是非老ie里是falsy
document.all // HTMLAllCollection(1208)
docuemnt.all && console.log('1') // HTMLAllCollection(1208)
new Boolean(docuemnt.all) // Boolean {false}
2.4 JSON.stringify (不是强制转换)
string、number、boolean、和null值在 JSON 字符串化时,与它们通过ToString抽象操作的规则强制转换为string值的方式基本上是相同的。
覆盖toJSON
var a = {
val: [1,2,3],
toJSON: function(){
return this.val.slice( 1 );
}
};
JSON.stringify(a) // '[2,3]'
3. 明确强制转换
var a = 42;
var b = String( a );
var c = "3.14";
var d = Number( c );
var a = 42;
var b = a.toString();
var c = "3.14";
var d = +c;
var c = "3.14";
var d = 5+ +c;
d; // 8.14
1 + - + + + - + 1; // 2
Date
var d = new Date( "Mon, 18 Aug 2014 08:53:06 CDT" );
+d; // 1408369986000
var d1 = new Date('2020-01-01')
var d2 = new Date('2020-01-02')
d2 - d1 // 86400000 == 1000*60*60*24
4. 抽象等价性
x == y
- 类型相同
NaN == NaN // false
+0 == -0 // true
object1 == object2 // false , object 不发生转换,比较引用
- 类型不同
null == undefined // true
1 == '1' // true 一个数字(Number、BigInt)和一个字符串比较,字符串转成数字
false == '1' // false 一个是boolean一个是其他基础类型,boolean转成数字比较
null == document.all
undefined == document.all
1 == object // 一个是object 一个是String, Number, BigInt, or Symbol, 对象转成原始值 ToPrimitive(y) (没传hint, 为default,和number一样转)
奇葩例子
Number.prototype.valueOf = function() {
return 3;
};
new Number( 2 ) == 3; // true
var i = 2;
Number.prototype.valueOf = function() {
return i++;
};
var a = new Number( 42 );
a == 2 && a == 3 // true
[] == ![]; // true
0 == "\n"; // true 各种空格的组合都会转成0
5. 抽象关系比较
x < y
步骤:
- 如果是x > y 转成 y < x
- x、y转成原始值,ToPrimitive(x, number),ToPrimitive(y, number)
- 如果x、y都是String
- 两个字符串逐位比较unicode码值(charCodeAt(i))
- 码值不同,返回码值的比较结果
- 码值相同,继续循环比较
- 循环结束,length小的 就小
- 如果x、y一个是String一个是BigInt
- String转成BigInt,转不成功是undefined,返回 undefined
- 转成功,比较bigInt
- 否则,都转成数字ToNumeric(Number,或者 BigInt)
- Symbol会抛出错误
- 其中一个是NaN,返回undefined
- 否则按值比较
这是按照最新规范2023整理的,实测返回undefined的情况都返回false