1. 令 toString 为用参数 "toString" 调用对象 O 的 [[Get]] 内部方法的结果。
2. 如果 IsCallable(toString) 是 true,则
1. 令 str 为用 O 作为 this 值,空参数列表调用 toString 的 [[Call]] 内部方 法的结果。
2. 如果 str 是原始值,返回 str。
3. 令 valueOf 为用参数 "valueOf" 调用对象 O 的 [[Get]] 内部方法的结果。
4. 如果 IsCallable(valueOf) 是 true,则
1. 令 val 为用 O 作为 this 值,空参数列表调用 valueOf 的 [[Call]] 内部方 法的结果。
2. 如果 val 是原始值,返回 val。
5. 抛出一个 TypeError 异常。
当用数字 hint 调用 O 的 [[DefaultValue]] 内部方法,采用以下步骤:
1. 令 valueOf 为用参数 "valueOf" 调用对象 O 的 [[Get]] 内部方法的结果。2. 如果 IsCallable(valueOf) 是 true,则
1. 令 val 为用 O 作为 this 值,空参数列表调用 valueOf 的 [[Call]] 内部方 法的结果。
2. 如果 val 是原始值,返回 val。
3. 令 toString 为用参数 "toString" 调用对象 O 的 [[Get]] 内部方法的结果。
4. 如果 IsCallable(toString) 是 true,则
1. 令 str 为用 O 作为 this 值,空参数列表调用 toString 的 [[Call]] 内部方 法的结果。
2. 如果 str 是原始值,返回 str。
5. 抛出一个 TypeError 异常。
-------------------------------------------------------
当不用 hint 调用 O 的 [[DefaultValue]] 内部方法,O 是 Date 对象的情况下 仿佛 hint 是字符串一样解释它的行为,除此之外仿佛 hint 是数字一样解释它 的行为。
上面说明的 [[DefaultValue]] 在原生对象中只能返回原始值。如果一个宿主对象 实现了它自身的 [[DefaultValue]] 内部方法,那么必须确保其 [[DefaultValue]] 内部方法只能返回原始值 /**************************************************************************************/var ob = {
toString: function () { return null; // 返回值必须是 primitive, 否则抛出错误 }, valueOf: function () { return '444'; }}console.log(ob + 'aaa', String(ob)) // 444aaa null
console.log(ob + 123, Number(ob)); // 444123 444// ...
/**************************************************************************************/ ToBoolean 输入类型 结果 Undefined false Null false Boolean 结果等于输入的参数(不转换) Number 如果参数是 +0, -0, 或 NaN,结果为 false; 否则结果为 true String 如果参数参数是空字符串(其长度为零),结果为 false,否则结果为 true。 Object true toBoolean 有些特殊, 比如 var v1 = new Boolean(false); Boolean(v1) // true; 个人认为: toBoolean 操作对原始值 (primitive) 的转换遵循规范上规则; 对于非原始值即转换为 true; 原始值 primitive: 指 Undefined, Null, Boolean, String, Number 原始值直接代表语言实现的最底层的数据。 /**************************************************************************************/ 说回正题: 强制类型转换: a. 显示强制类型转换: 即强制将一个类型值转换为另一个类型值; 比如我们常用的: Number('123'); //123, String(345); //'345' 1. 字符串和数字之间的显式转换: 通过 String(..) 和 Number(..) 这两个内建函数来实现的; String(..) 遵循上面讲的 ToString 规则 Number(..) 遵循上面讲的 ToValue 规则 2. 显式转换为布尔值: Boolean() 遵循上面讲的 toBoolean 规则
'111' == 111; // true 一个是数字一个是字符串, 如何比较相等; 转换值类型应该是都转换为数值再比较; 还是都转换为字符串再作比较;if ('111') {...} //if 中本应该是一个布尔值, 字符串如果判断, 又需要将字符串转换为布尔值'345' + 12; // 34512 数字和字符串如何相加,又如何转换值类型; 到底是认为两个都是字符串, 执行字符串拼接; 还是认为两个都是数字, 执行数学运算;'222' % 2; // 0 字符串又如何能够进行模运算, 所以又需要将值转换为数字再进行运算;~'222'; // -233 先对 '222' 值 toNumber得到 222 再 ToInt32 转换为32位整数, 再执行字位操作 ~(对每一个字位进行反转), 得到 -223; ['2'] + 333; // 2333 类似的...
这里面涉及到了几乎所有的运算符 如: 一元位运算: 1. 前自增 2. 前自减 3. 一元 + 运算符 4. 一元 - 运算符 5. 按位非运算符 6. 逻辑非运算符 乘法运算符 1. 使用 * 运算符 2. 使用 / 运算符 3. 使用 % 运算符 加法运算符 1. 加号运算符 + 2. 减号运算符 - 位运算移位运算符, ... 比较运算符: 1. < , <= 2. > , >= 3. 抽象关系比较: 详细定义请见 ECMA-262规范中定义 等值运算符: 1. == 2. != 还有二元逻辑运算 (&&, ||), 条件运算 (?) 里面都会涉及到类型转换。但无论怎样, 类型转换都离不开 toNumber, toString, toBoolean 这几种操作; 到底是应该 toNumber, 还是 toString, 亦或 toBoolean, 得视具体情况来定。 其他更加详细的内容, 请参阅规范或是其他书籍。