为什么(“ foo” === new String(“ foo”))在JavaScript中评估为false?


98

在比较字符串值时,我一直都在开始使用===(三等分,严格比较),但是现在我发现

"foo" === new String("foo")

是错误的,与此相同:

var f = "foo", g = new String("foo");
f === g; // false

当然:

f == g; // true

因此,建议始终使用==进行字符串比较,还是始终在比较之前将变量转换为字符串?


6
也许是因为foo是纯字符串,new String("foo")而是对象字符串
Danilo Valente 2012年


6
建议不要使用new String(完全毫无意义)创建字符串,而不要使用==
Esailija 2012年

2
为什么有人首先要使用像new String("foo")Javascript 这样的构造?我从未在代码中看到过这样的代码,即jQuery ...
Robert Koritnik 2012年

2
String(obj)收到“字符串”参数后,您可以用于将装箱的字符串转换为原始字符串。("foo" === String(new String("foo"))) === true
OrangeDog 2012年

Answers:


126

"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对象。


33
+1 typeof "foo"; // "string"typeof new String("foo"); // "object"
桑普森

1
有趣的是,我认为字符串是JS中的对象。
卡梅隆·马丁

1
@Sarfraz:几乎所有东西。不要忘记nullundefined

2
if( Object(a) !== a ) { //it's a primitive }
Esailija 2012年

1
Java确实具有基元/.Net却没有
Marcelo De Zen

34

使用===

  • 一个对象永远不会等于任何东西,除了另一个对其自身的引用。

  • 如果一个原语的类型和值相同,则与另一个原语相比是相等的。


3
new String("foo") === new String("foo")false:-P
火箭危险物

10

这个new词在这里是罪犯(我可以照常说)...

使用时new,您明确表达了使用对象的愿望。这可能会让您感到惊讶,但这是:

var x = new String('foo');
var y = new String('foo');
x === y; 

...会给你强大的力量false。很简单:比较的不是对象的内部,而是对象的引用。当然,它们是不相等的,因为创建了两个不同的对象。

您可能要使用的是conversion

var x = String('foo');
var y = String('foo');
x === y;

...这将为您带来预期的true结果,因此您可以foos永远平等地为之欢欣和繁荣。)


2
有关使用此功能的快速问题。您正在调用不带'new'关键字的String(构造函数?)。这是否意味着您将使用String构造函数内分配的任何属性来污染范围?还是因为构造函数是本机代码而不会发生?换句话说,假设String函数包含“ this.a = 1;”。-这意味着你的函数/对象现在将属性A = 1,有
迈克尔·巴特勒

我想(但不能肯定地说)每个“装箱构造函数”函数首先检查其上下文-如果它不是“新的”(即原型对象),则立即切换到转换方法。例如,在使用String的情况下toString()
raina77ow 2012年


2

从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'
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.