抽象值操作
掌握字符串、数字和布尔值之间类型转换基本规则
ToString
ToString,它负责处理非字符串到字符串的强制类型转换
基本类型值的字符串化规则为:
null 转换为 “null”,undefined 转换为 “undefined”,true 转换为 “true”。
注意点:
极小和极大的 数字使用指数形式:
// 1.07 连续乘以七个 1000 var a = 1.07 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000;
// 七个1000一共21位数字 a.toString(); // "1.07e21"
普通对象返回内部属性(除非自定义)
(Object.prototype.toString()
数组转字符串
数组的默认 toString() 方法经过了重新定义,将所有单元字符串化以后再用 “,” 连接起 来。
var a = [1,2,3];
a.toString(); // "1,2,3"
JSON 字符串
JSON 字符串化和 toString() 的效果基本相同,所有安全的JSON 值(JSON-safe)都可以使用JSON.stringify(…) 字符串化。
什么是不安全的JSON 值。
undefined、function、symbol (ES6+)和包含循环引用(对象之间相互引用,形成一个无限循环)的对象都不符合 JSON 结构标准,支持 JSON 的语言无法处理它们。
JSON.stringify(…) 在对象中遇到 undefined、function 和 symbol 时会自动将其忽略,在 数组中则会返回 null(以保证单元位置不变)。
例如:
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}"
对包含循环引用的对象执行 JSON.stringify(…) 会出错。
如果要对含有非法 JSON 值的对象做字符串化,或者对象中的某些值无法被序列化时,就 需要定义 toJSON() 方法来返回一个安全的 JSON 值。
var o = { };
var a = { b: 42, c: o, d: function(){} };
// 在a中创建一个循环引用 o.e = a;
// 循环引用在这里会产生错误 // JSON.stringify( a );
// 自定义的JSON序列化 a.toJSON = function() { // 序列化仅包含b return { b: this.b }; };
JSON.stringify( a ); // "{"b":42}"
总结
- 字符串、数字、布尔值和 null 的 JSON.stringify(…) 规则与 ToString 基本相同。
- 如果传递给 JSON.stringify(…) 的对象中定义了 toJSON() 方法,那么该方法会在字符 串化前调用,以便将对象转换为安全的 JSON 值。
ToNumber
true 转换为 1,false 转换为 0。undefined 转换为NaN,null 转换为 0。
从 ES5 开始,使用 Object.create(null) 创建的对象 [[Prototype]] 属性为 null,并且没 有 valueOf() 和 toString() 方法,因此无法进行强制类型转换。
ToBoolean
以下这些是假值:
- undefined
- null
- false
- +0、-0 和 NaN
- “”
假值的布尔强制类型转换结果为 false,其余都为真值。
显式强制类型转换
字符串和数字之间的转换
字符串和数字之间的转换是通过 String(…) 和 Number(…)这两个函数来实现的
var a = 42; var b = String( a );
var c = "3.14"; var d = Number( c );
b; // "42" d; // 3.14
除了String() 和Number()以外的其他方法。
var a = 42; var b = a.toString();
var c = "3.14"; var d = +c;
b; // "42" d; // 3.14
a.toString() 是显式的(“toString”意为“to a string”),不过其中涉及隐式转换。因为 toString() 对 42 这样的基本类型值不适用,所以 JavaScript 引擎会自动为 42 创建一个封 装对象,然后对该对象调用 toString()。这里显式转换中含有隐式转换。
上例中 +c 是 + 运算符的一元(unary)形式(即只有一个操作数)。+ 运算符显式地将 c 转 换为数字,而非数字加法运算
但是这样会产生误会:
var c = "3.14"; var d = 5+ +c;
d; // 8.14
所以我们需要注意:
1 + - + + + - + 1; // 2
所以尽量不要把一元运算符 +(还有 -)和其他运算符放在一起使用。
数字和字符串的解析
解析允许字符串中含有非数字字符,解析按从左到右的顺序,如果遇到非数字字符就停 止。而转换不允许出现非数字字符,否则会失败并返回 NaN。
var a = "42"; var b = "42px";
Number( a ); // 42 parseInt( a ); // 42
Number( b ); // NaN parseInt( b ); // 42
非字符串参数会首先被强制类型转换为字符串,但是__需要注意__
避免向 parseInt(…) 传递非字符串参数
我们先来看一个例子:
parseInt( 1/0, 19 ); // 18
parseInt(1/0, 19) 实际上是 parseInt(“Infinity”, 19)。第一个字符是 “I”,以 19 为基数 时值为 18。第二个字符 “n” 不是一个有效的数字字符,解析到此为止,和 “42px” 中的 “p” 一样。
所以我么可以解释的通所有的类似的值了
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
显示转换为boolean
我们来看看从非布尔值强制类型转换为布尔值的情况
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
和前面讲过的 + 类似,一元运算符 ! 显式地将值强制类型转换为布尔值。
var a = "0";
var b = [];
var c = {};
var d = "";
var e = 0;
var f = null;
var g;
!!a; // true
!!b; // true
!!c; // true
!!d; // false
!!e; // false
!!f; // false
!!g; // false