【发布时间】:2010-10-15 18:55:11
【问题描述】:
Javascript 有很多关于类型和类型转换的“技巧”,所以我想知道这两种方法是否相同,或者是否有一些极端情况使它们不同?
【问题讨论】:
标签: javascript
Javascript 有很多关于类型和类型转换的“技巧”,所以我想知道这两种方法是否相同,或者是否有一些极端情况使它们不同?
【问题讨论】:
标签: javascript
它们并不完全相同,实际上the String constructor called as a function(你的第一个例子)最后会调用传递对象的toString方法,例如:
var o = { toString: function () { return "foo"; } };
String(o); // "foo"
另一方面,如果一个标识符引用null或undefined,你不能使用toString方法,它会给你一个TypeError异常:
var value = null;
String(null); // "null"
value.toString(); // TypeError
作为函数调用的String 构造函数大致相当于:
value + '';
从Object到Primitive的类型转换规则在规范中有详细描述,[[DefaultValue]]内部操作。
简单总结一下,从Object到String的转换,有以下几个步骤:
toString 方法。
result 是原语,则返回result,否则转到步骤2。valueOf 方法。
result 是原语,则返回result,否则转到步骤3。TypeError。鉴于以上规则,我们可以举例说明所涉及的语义:
var o = {
toString: function () { return "foo"; },
valueOf: function () { return "bar"; }
};
String(o); // "foo"
// Make the toString method unavailable:
o.toString = null;
String(o); // "bar"
// Also make the valueOf method unavailable:
o.valueOf = null;
try {
String(o);
} catch (e) {
alert(e); // TypeError
}
如果您想了解有关此机制的更多信息,我建议您查看ToPrimitive 和ToString 内部操作。
我也推荐阅读这篇文章:
【讨论】:
new String(value),它总是会返回一个字符串对象。
new String({toString: null}) 抛出 TypeError。
String() 和+ '' 现在有相当显着的区别。 String(Symbol()) 会运行,但 Symbol() + '' 会抛出一个错误(并且 Symbol() 会传递一个虚假的守卫,不像 null 和 undefined,所以 x && (x + '') 现在可以抛出)。
如果value 为空或未定义,value.toString() 将导致错误。 String(value) 不应该。
例如:
var value = null;
alert(value.toString());
将失败,因为value == null。
var value = null;
alert(String(value));
应该显示一条消息“null”(或类似的),但它不会崩溃。
【讨论】:
String(value) 在任何情况下都应该与value.toString() 具有相同的结果,除了没有null 或undefined 等属性的值。 ''+value 将产生相同的结果。
【讨论】:
String() [构造函数调用] 基本上是调用 .toString()
.toString() 和 String() 可以在原始值(数字、布尔值、字符串)上调用,基本上不会做任何特别的事情:
真 => '真'
假 => '假'
17 => '17'
'你好' =>'你好'
但是在对象上调用这些函数才是有趣的地方:
如果对象有它自己的 .toString() 函数,它将在您需要将此对象视为字符串时调用(显式/隐式)
let obj = {
myName:"some object",
toString:function(){ return this.myName; }
}
//implicitly treating this obj as a string
"hello " + obj; //"hello some object"
//OR (explicitly)
"hello " + String(obj) //calling the existent toString function
//OR
"hello " + obj.toString(); //calling toString directly
顺便说一句,如果你想将此对象视为一个数字,它应该有一个 .valueOf() 函数在其中定义。
如果我们将两者都放在一个对象中会怎样?
如果我们想将此对象视为字符串 => 使用 .toString()
如果我们想将此对象视为数字 => 使用 .valueOf()
如果我们只定义了 .valueOf() 会怎样?
.valueOf() 定义在对象内部,无论我们想将对象作为字符串还是数字处理,都会被调用
【讨论】:
我刚刚在 ES6 上尝试过,发现要让String() 查看对象内部的valueOf(),对象必须有toString() 方法。如果对象没有toString(),那么无论是否有valueOf(),控制台都会返回'[object Object]'。所以在第一个“步骤”中,我们总是必须有toString(),否则String() 方法不会查看valueOf。
请检查:
let obj = {
name:'b',
age:22,
valueOf: function(){
return 'heeee';
}
}
String(obj); // prints '[object Object]'
另一方面,
let obj = {
name:'b',
age:22,
toString:null,
valueOf: function(){
return 'heeee';
}
}
String(obj); // prints 'heeee'
let obj = {
name: 'b',
age: 22,
valueOf: function() {
return 'heeee';
}
}
console.log(String(obj));
let obj2 = {
name: 'b',
age: 22,
toString: null,
valueOf: function() {
return 'heeee';
}
}
console.log(String(obj2));
【讨论】: