我打算在比较字符串值时一直使用 ===(三重等于,严格比较),但现在我发现
"foo" === new String("foo")
是假的,与此相同:
var f = "foo", g = new String("foo");
f === g; // false
当然:
f == g; // true
那么是建议始终使用==进行字符串比较,还是在比较之前始终将变量转换为字符串?
我打算在比较字符串值时一直使用 ===(三重等于,严格比较),但现在我发现
"foo" === new String("foo")
是假的,与此相同:
var f = "foo", g = new String("foo");
f === g; // false
当然:
f == g; // true
那么是建议始终使用==进行字符串比较,还是在比较之前始终将变量转换为字符串?
"foo"
是一个字符串原语。(这个概念在 C# 或 Java 中不存在)
new String("foo")
是装箱字符串对象。
该===
运营商的行为有所不同的原语和对象。
比较基元(相同类型)时,===
如果它们都具有相同的值,则返回 true。
比较对象时,===
仅当它们引用同一个对象时才返回 true(按引用进行比较)。因此,new String("a") !== new String("a")
。
在您的情况下,===
返回 false 因为操作数的类型不同(一个是原始类型,另一个是对象)。
基元根本不是对象。
该typeof
运营商将不会返回"object"
原语。
当您尝试访问原始对象的属性(将其用作对象)时,Javascript 语言会将其装箱为一个对象,每次都创建一个新对象。这在规范中有所描述。
这就是您不能将属性放在基元上的原因:
var x = "a";
x.property = 2;
alert(x.property) //undefined
每次编写时x.property
,都会创建一个不同的装箱String
对象。
使用===
,
除了对自身的另一个引用之外,对象永远不会等于任何东西。
如果它们的类型和值相同,则一个原语与另一个原语相比是相等的。
这个new
词在这里是一个罪犯(像往常一样,我可以说)......
当您使用 时new
,您明确表达了使用object 的愿望。这可能会让你感到惊讶,但这个:
var x = new String('foo');
var y = new String('foo');
x === y;
...会给你一个强大的false
。很简单:比较的不是对象的内部,而是对象的引用。当然,它们并不相等,因为创建了两个不同的对象。
您可能想要使用的是转换:
var x = String('foo');
var y = String('foo');
x === y;
......正如预期的那样,这会给您带来true
结果,因此您可以foos
永远与平等的人一起快乐和繁荣。)
foo
是纯字符串,new String("foo")
是对象字符串
从 node.js REPL(如果安装了命令行上的“节点”):
> "foo" === (new String("foo")).valueOf()
true
> "foo" === new String("foo")
false
> typeof("foo")
'string'
> typeof(new String("foo"))
'object'
> typeof((new String("foo")).valueOf())
'string'