将值从一种类型转换为另一种类型,a -> ‘a’ ,称为类型转换。转换分为两种,一种显式的,一种隐式的,隐式的往往也是强制类型转换。强制类型转换总是返回标量基本类型,不会返回对象和函数。
如何区分?
类型转换(显式),通常发生在静态类型语言的编译阶段,而强制类型转换则发生在动态类型语言的运行时。
例如:
var a = 123
var b = a + '' // '123' 隐式强制类型转换
var c = String(a) // '123' 显示强制类型转换
基本字符串化规则:
null -> 'null'
undefined -> 'undefined'
true -> 'true'
1 -> '1'
稍微特殊一点的情况
var a = 1.02 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000
console.log(a.toString()) // '1.02e+21'
数组的 toString 方法经过了重新定义,返回 每个元素使用 ,
拼接的字符串
var arr = [1,2,3]
arr.toString() // '1,2,3'
toString 可以显式调用,也会在需要的时候自动调用
工具函数 JSON.stringfy() 在将 JSON 对象序列化为字符串也用到了 toString 方法
对于大多数简单值,JSON.stringfy() 和 toString 基本相同
JSON.stringify(123) // "123"
JSON.stringify("123") // ""123"" 在JSON中,所有的字符串都必须用引号括起来。即使在一些浏览器没有显示想要的结果
JSON.stringify(null) // "null"
JSON.stringify(undefined) // "undefined"
JSON.stringify() 在对象中遇见 undefined、function 和 Symbol 是会自动忽略,在数组中碰到就会返回 null
JSON.stringify(undefined) // undefined
JSON.stringify(function(){}) // undefined
JSON.stringify([1,nudefined,function(){},4]) // "[1,null,null,4]"
JSON.stringify({a:2,b:function(){}}) // "{"a":2}"
如果对象里定义了 toJSON方法,JSON.stringify() 会首先调用该方法,然后用返回值执行 JSON.stringify() ,这( toJSON方法)一般用于返回一个安全可被序列化的值。注意:toJSON 不是返回一个 JSON 字符串。
JSON.stringify() 的额外参数
var obj = {
a: 1,
b: 'bbb',
c: [1,2,3]
}
console.log(JSON.stringify(obj, [a, b])) // "{"a":1,"b":"bbb"}"
const res = JSON.stringify(obj, function(k,v){
if( k !== 'c') {
return v
}
})
console.log(res) // "{"a":1,"b":"bbb"}"
JSON.string 还有一个可选参数 space,用来指定输出的缩进格式。space 为正整数时是指定每一级缩进的字符数,它还可以是字符串,此时最前面的十个字符被用于每一级的缩进
var a = {
b: 42,
c: "42",
d: [1,2,3]
};
JSON.stringify( a, null, 3 );
// {
// "b": 42,
// "c": "42",
// "d": [
// 1,
// 2,
// 3
// ]
// }
JSON.stringify( a, null, "-----" );
// "{
// -----"b": 42,
// -----"c": "42",
// -----"d": [
// ----------1,
// ----------2,
// ----------3
// -----]
// }"
字符串、数字、布尔值和null的 JSON.stringify() 与 ToString 基本相同
如果传递给 JSON.stringify(…) 的对象中定义了 toJSON() 方法,那么该方法会在字符串化前调用,以此将对象转换为可字符串化的 JSON 值。
对于一些非数字值当作数字来进行运算,会发生以下转换:
可以看出,toNumber 基本符合数字常量计算的规则,处理失败返回 NaN。
注意:ToNumber 对 0 开头的数字会按照十进制处理,而不是八进制。
ToPrimitive是一个抽象操作,在将值转换为相应的基本类型值时使用。它首先检查该值是否有valueOf()方法。如果有并且返回一个基本类型值,就使用该值进行强制类型转换。如果没有valueOf()方法,就会检查是否有toString()方法。如果存在toString()方法并且返回一个基本类型值,就使用该值进行强制类型转换。
但是从 ES5 开始,使用 Object.create(null) 创建的对象没有原型上的方法。所以无法强制类型转换。
var a = {
valueOf: function(){
return "42";
}
};
var b = {
toString: function(){
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
在 JavaScript 中,1 不等于 true,而 0 也不等于 false ,这是无法一概而论的。
1.4.1 假值
JavaScript 中有以下假值:
如果我们不考虑 JavaScript 的规范,除了上述假值之外,其他的值都应该视为真值。
1.4.2 假值对象
var a = new Boolean( false );
var b = new Number( 0 );
var c = new String( "" );
假值对象并非包含了假值的对象…
var res = Boolean(a && b && c)
console.log(res) // true
假值对象是浏览器在特定情况下创建的外来值,尽管它们看起来像普通对象,但在布尔强制类型转换时结果为false。其中一个常见的例子是document.all,它以前是一个真值对象,但现在是一个假值对象。为了符合标准,IE不再支持使用if(document.all){…}。虽然我们无法完全摆脱document.all,但可以考虑修改JavaScript的类型机制来处理它。****
1.4.3 真值
真值就是除了假值之外的值。
显式类型转换,顾名思义,是在 JavaScript 中强制把一种数据类型变为另一种数据类型。JavaScript是动态类型的编程语言,但有时我们为了某些逻辑需要将一个数据类型强制转换为另一个数据类型,此时就会用到显式类型转换。
主要有以下几种方式:
Number()
:将其他任何数据类型转换为数字。String()
:将其他任何数据类型转换为字符串。Boolean()
:将其他任何数据类型转换为布尔值。这是一些简单的示例:
// 将数字转为字符串
let num = 123;
let str1 = String(num); // 显式转换
console.log(typeof str1); // 输出 'string'
// 将布尔值转为字符串
let bool = true;
let str2 = String(bool); // 显式转换
console.log(typeof str2); // 输出 'string'
// 将字符串转为数字
let strNum = "123";
let number = Number(strNum); // 显式转换
console.log(typeof number); // 输出 'number'
// 将字符串转为布尔值
let strBool = "true";
let boolean = Boolean(strBool); // 显式转换,任何非空字符串都会转为 true
console.log(boolean); // 输出 true
这些是显式类型转换在JavaScript中的基本用法
还可以通过
+
、-
、~
、!!
等等符号操作来进行类型转换
加号 (+) :将任何非 string 类型的值转换为 string 类型。
var num = 15;
console.log(typeof +num); // "number"
console.log(typeof (+num + "")); // "string"
在这个例子中, “+num” 仍然是一个数字。但是,当我们通过 “+num + “”” 将字符串与数字连接起来时,整个表达式将是字符串类型。
减号 (-):将字符串类型的数字值转换为 number 类型。
var strNum = "123";
console.log(typeof strNum); // "string"
console.log(typeof -strNum); // "number"
然而,“-strNum”是一个负数,所以你可能需要再次使用 “-” 操作符来恢复其原始正值。
非 (~):在 JavaScript 中,非运算符 “~” 可以用于数组查找或者用来替代条件语句。“~” 运算符会将数字翻转,即计算其一补数。在类型转换中,它并非常用。
// 使用 "~" 运算符和 "indexOf()" 方法从数组中查找字符串 "word"
// 如果 "word" 不在数组中,"indexOf()" 将返回 -1,"~" 将其改变为 0;否则,"~" 会把 "indexOf()" 返回的任何其他数值(代表 "word" 在数组中的位置)改变为一个非零数值
var index = ~someArray.indexOf("word");
// 如果 "index" 是非零值(意味着找到了 "word"),则执行 if 后面的代码块;如果是 0(意味着没有找到 "word"),则不执行
if (index)
// 与上面的代码基本同样的逻辑,但是省略了定义变量 "index" 的步骤。它直接在 "if" 条件中进行查找和 "~" 运算,然后根据返回的是否为零值来决定是否执行后面的代码块
// 同样,如果找到了 "word",则执行 if 后的代码块;如果没有找到,不执行
// 这种写法更简洁,但可能在某些情况下可读性更差
if(~someArray.indexOf("word"))
双非 (!!):将任何非 boolean 类型的值转化为 boolean 类型。这个运算符被称为 “双否运算符”,会将值转换为真实的逻辑布尔值(true 或 false)。
var name = "AI";
console.log(typeof !!name); // "boolean"
“!!name”返回的是 “true”,因为我们对一个非空的字符串使用了 “!!” 操作符。