为什么在JavaScript中,("foo" === new String("foo"))的求值结果为false?

20 浏览
0 Comments

为什么在JavaScript中,("foo" === new String("foo"))的求值结果为false?

我原本打算在比较字符串值时始终使用 ===(三等号,严格比较),但现在我发现

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

是错误的,下面的也是一样的:

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

当然:

f == g; // true

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

0
0 Comments

为什么JavaScript中的"foo" === new String("foo")会返回false?

在JavaScript中,"foo"是一个字符串原始值,而new String("foo")是一个装箱的字符串对象。在比较运算符===中,对于原始值和对象的比较行为是不同的。

当比较两个相同类型的原始值时,如果它们的值相等,===会返回true。

而当比较两个对象时,===只有在它们引用同一个对象时才会返回true(按引用比较)。因此,new String("a") !== new String("a")。

在这个问题中,===返回false是因为操作数的类型不同(一个是原始值,一个是对象)。

原始值本身并不是对象。使用typeof运算符对原始值进行操作时,不会返回"object"。

当你尝试访问原始值的属性时,JavaScript语言会将其转换为一个对象,每次都会创建一个新的对象。这在规范中有描述。

这就是为什么你不能在原始值上添加属性。

每次你写x.property时,都会创建一个不同的装箱的String对象。

typeof "foo"; // "string"

typeof new String("foo"); // "object"

有趣的是,我以为字符串在JavaScript中是对象。

一切都可以是对象,甚至是字符串,只要你创建一个实例。

几乎一切都可以,不要忘记null和undefined。

遗憾的是,typeof对于一个原始值确实返回"object"。

if( Object(a) !== a ) { //it's a primitive }

如果字符串不是对象,为什么它们有属性和方法?

当你像使用对象一样使用字符串原始值时,它会被临时转换为对象。

在Java中,确实有原始值,而在C#中没有。在C#和Java中,String是一个普通的类(引用类型)。在.NET中,String更接近原始值;它在IL中有特殊支持(用于字面量)和GC/内存模型(它们不是固定大小的)。.NET和Java都有原始数值类型。

但是,在Java中,字符串的interning导致了一些相关的语义:stackoverflow.com/questions/2486191/…

0
0 Comments

使用===,对象只等于其本身的另一个引用。

如果原始值的类型和值都相同,它们在比较时是相等的。

所以new String("foo") === new String("foo")是false。

0
0 Comments

在JavaScript中,为什么`("foo" === new String("foo"))`的结果是`false`呢?原因在于`new`关键字的使用。

当使用`new`关键字时,你明确表达了你希望使用一个对象。也许会让你感到惊讶,但是下面这段代码:

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

...将会得到一个`false`的结果。原因很简单:比较的不是对象的内部内容,而是对象的引用。由于创建了两个不同的对象,它们的引用自然不相等。

你可能想要使用的是类型转换:

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

...这将会得到预期的`true`结果,这样你就可以永远拥有相等的`foo`了。

还有一个关于使用这个方法的问题:你在没有使用`new`关键字的情况下调用了`String`(一个构造函数?)。这是否意味着你会在`String`构造函数中污染作用域,添加任何分配的属性呢?或者这种情况不会发生,因为构造函数是原生代码?换句话说,假设`String`函数中包含了`this.a = 1;` —— 这意味着你的函数/对象现在有了一个属性`a = 1`。

我猜(但不能确定),每个“包装构造函数”函数首先检查它的上下文,如果它不是一个“新的”(即原型对象)上下文,就会立即切换到转换方法。例如,对于`String`来说,就是`toString()`方法。

总结起来,当使用`new`关键字时,会创建一个新的对象引用,导致比较结果为`false`。而使用类型转换时,会得到预期的相等结果。

0