简体   繁体   English

JS:怪异的对象比较行为

[英]JS: weird object comparison behavior

Given this code: 给出以下代码:

 const name = { name: 'amy' }; function greet(person) { if (person == { name: 'amy' }) { return 'hey amy'; } else { return 'hey there'; } } console.log( greet(name) // 'hey amy' ); console.log( greet({ name:'amy' }) // 'hey there' ); console.log(name == { name: 'amy' }); // true console.log(name === { name: 'amy' }); // false console.log(Object.is(name, { name: 'amy' })); // false 

Why does double-equals comparison return true when using the name variable, but not an object literal? 为什么在使用name变量而不是对象文字时双精度比较返回true

First, I thought that maybe it's because the objects have the same memory address, but as one can see it's not true. 首先,我认为可能是因为对象具有相同的内存地址,但是正如人们看到的那样,这是不正确的。

Moreover, if we turn things upside-down and define the variable inside the function, the comparison returns false ! 而且,如果我们颠倒过来并在函数内部定义变量,则比较返回false (It is not shown in the code but you can check it out) (代码中未显示,但您可以签出)

I'm seriously confused and will appreciate the explanation. 我很困惑,不胜感激。

EDIT: Here is where I have tested the code. 编辑: 是我测试过代码的地方。 Nodejs and browser console in Chrome give me the regular results, how it should be. Chrome中的Nodejs和浏览器控制台为我提供了常规结果,应该是这样。 So maybe it is something about the interpreter. 所以也许是关于口译员的事。

You assume that Javascript will perform the comparision with == as you are thinking of it in your mind, but it is not. 您假定您在脑海中就想着Javascript将使用==进行比较,但事实并非如此。 But as this is a custom object you can't expect Javascript to hand you a custom implementation out of the box. 但是由于这是一个自定义对象,所以您不能指望Javascript会为您提供自定义实现。 You should implement it yourself. 您应该自己实现它。

The only case where this would work is when you use the === operator to check whether the object are the same but by their memory address, thus skipping any custom-object-data-based comparison whatsoever. 唯一可行的情况是,使用===运算符检查对象是否相同,但按其内存地址进行检查,从而跳过任何custom-object-data-based比较。

The problem here is the use of the word name for your variable. 这里的问题是为变量使用单词name

In a browser, the window object has a name property that must always be a string. 在浏览器中, window对象具有name属性,该属性必须始终为字符串。 If you try to assign something to it that is not a string, it will be converted to one. 如果您尝试为其分配非字符串的内容,它将被转换为一个。

Then, when you compare an object with a string, the object will also be converted and the two strings compared. 然后,当您将一个对象与一个字符串进行比较时,该对象也将被转换并比较两个字符串。 This is why you see it sometimes return true. 这就是为什么您看到它有时返回true的原因。 Example: 例:

 // This will end up being assigned to window.name, and will be converted to a string. var name = {name: "amy"} console.log(name) // [object Object] // Then, when you compare that to another object using ==, the object will also be converted to string. console.log(name == {name: "amy"}) // true, because the string [object Object] is equal to itself. 

Change the name of the variable to anything else, or use let or const , and the problem should disappear: 将变量的名称更改为其他名称,或者使用letconst ,问题应消失:

 // This will end up being assigned to window.other, but isn't converted to string var other = {name: "amy"} console.log(other) // {"name": "amy"} // Now, both are objects, and unless they are the exact same object, comparing two objects is always false. console.log(other == {name: "amy"}) // false, no two distinct objects are ever equal 

 // Using let will not assign this variable to window. let name = {name: "amy"} console.log(name) // {"name": "amy"} // Again, now we compare two distict objects, which always results in false. console.log(name == {name: "amy"}) // false 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM