这三种将value转换为字符串的方法是:
1. value.toString()
2. “” + value
3. String(value)
第一种方法不推荐
因为null和undefined去调用toString方法会报错
第二种和第三种方法的效果基本一样
- “” + value这种方法熟悉使用的人很容易理解,而且方便,但是它的可读性是很差的,不利于代码的维护。
- String(value):这种方法可读性更好,唯一的问题是,这种函数调用可能会迷惑人。因为String同时也是一个构造函数,但是它作为普通函数和作为构造函数时的表现完全不同。
String('abc') === new String('abc');
> false
typeof String('abc');
> 'string'
typeof new String('abc');
> 'object'
String('abc') instanceof String;
> false
new String('abc') instanceof String;
> true
String作为一个普通函数会产生一个字符串(原始值)
String作为一个构造函数时会产生一个String对象的实例
“”+value 和 String(value)的细微差别
这两种方法都是使用引擎内部的ToString()操作将原始值转换为字符串。
“内部操作”的意思是:这个操作函数是在ECMAScript5.1中定义的,但是ES语言本身并不能访问到它,下面的表格解释了ToString()是如何转换原始值的。
将原始值转换为字符串
参数 | 结果 |
---|---|
undefined | “undefined” |
null | “null” |
布尔值 | “true”或”false” |
数字 | 数字作为字符串 |
字符串 | 无需转换 |
将对象转换为字符串
这两种方法都将对象值先转化为原始值,然后再将原始值转化为字符串。
但是在这个过程之中
+使用的是内部的ToPrimitive(Number)操作(除非被转化的对象是date对象),
而String()用的是ToPrimitive(String)。
- ToPrimitive(Number):将一个对象转换为原始值,首先调用obj.valueOf()。如果返回值是一个原始值,则返回这个原始值,如果不是,再调用obj.toString()。如果返回的值是原始值,则返回这样原始值,否则,抛出TypeError异常。
- ToPrimitive(String):和上面的方法类似,只是先调用obj.toString()方法。
通过案例查看
var obj = {
valueOf:function(){
console.log('valueOf');
return {};//不是原始值,继续执行
},
toString:function(){
console.log('toString');
return {};//不是原始值,继续执行
}
}
// 运行
> "" + obj
valueOf
toString
TypeError: Cannot convert object to primitive value
> String(obj)
toString
valueOf
TypeError: Cannot convert object to primitive value
通常结果总相同
上面讲的区别,在实际情况中几乎不太可能遇到,因为:大部分的对象都使用了默认的valueOf()方法,返回的值总是这个对象本身。
> var x = {}
> x.valueoOf() === x
true
因此,ToPrimitive(Number)通常会跳过valueOf方法返回toString()方法的返回值,这就表现的和ToPrimitive(String)完全一样,但是,如果这个对象是Boolean,Number或者String的对象实例,那么它的valueOf()会返回一个原始值(被这个对象包装前的原始值),那么这两种操作就会按照如下步骤执行:
- ToPrimitive(Number)返回了对象的valueOf()方法的返回值(被包装前的原始值)再经过ToString()操作后的结果
- ToPrimitive(String)返回了对象的toString()方法的返回值(在该对象被包装前的原始值上进行ToString()操作的返回值)。
就这样,他们还是返回了相同的结果,只是转换的途径不同。
结论
你应该选择哪种方式来将其他类型的值转换为字符串呢?
如果你能确保这个值永远不会是null或者undefined,则可以用value.toString()来转换,否则,”“+value和String(value)选择哪一个都可以,看个人喜好,个人认为String(value)更明确一点。