Javascript: 为什么两个对象不相等?
Javascript: Why are two objects not equal?
我知道在 SO 上有类似的问题,但其中 none 提供了我正在寻找的答案。
在JavaScript中,如果执行以下操作,结果将为假:
我知道这与 JavaScript 在规范中的定义有关,但为什么会这样?这是违反直觉的。
如果 ("string" === "string")
结果为 true
,那么为什么 ({ } === { })
不为真?
我在某处看到平等算法被设计为类似于 C++ 或 C# 的算法,但这就像发明一种全新的引擎,使用 1/10 的燃料,而不是纯粹为了与其他汽车保持一致而使用它.
为什么 JavaScript 是这样定义的?这个决定背后有什么原因吗?还是只是为了让人看到它在做这件事?
字符串是不可变的,因此具有相同内容的两个字符串在功能上是无法区分的。
但是对象和数组是可以修改的,因此仅仅因为它们在某个特定时间碰巧具有相同的内容并不意味着它们是相同的。你可以修改它们,然后它们就会不同。
另一种说法是,如果 obj1 == obj2
为真,那么当您执行 obj1.x = 1
时,它也会更改 obj2.x
。
{}
是在javascript中创建对象的文字。那就是你可以替换
var obj = new Object();
和
var obj = {};
所以任何时候你使用 {}
你都在创建一个新对象。
您提到的行 {} == {}
创建了两个不同的对象,并且都没有属性。相同地,它们是相同的,就像如果你有 equals(obj1, obj2)
方法比较 obj1 和 obj2 的属性,如果两者的所有属性值都相同,它应该 return 为真。
但是 ==
运算符不会检查属性。它检查两个对象是否指向相同的 object/reference.
而
var obj1 = {};
obj2 = obj1;
console.log(obj2 == obj1); //returns true
return为真,因为 obj1 和 obj2 指向相同的引用。
最后,关于字符串 "abc" == "abc"
,此处 ==
运算符查找实际的字符串内容,并根据它 returns true/false。
因为 javascript 中的字符串即使是一个对象也被认为是基元,就像整数或布尔值一样,并且它们总是按值进行比较,因为这就是基元,一个简单的原子值.. 所以 "string" == "string"
, 1 = 1
和 true == true
,
但是对象是复杂的类型,它们是基元的集合,比较那个集合的规则,不能简化为标准,是{name:'a',address:'b',phone:'c'} != {name:'a',address:'b'}
因为没有相同数量的属性吗?那么在那种情况下会 {name:'x',address:'y'} == {name:'a',address'b'}
吗?它们具有相同的属性,但具有不同的值,或者使其更复杂 {name:'x',address'y'} == {address:'y',name:'c'}
..顺序是否重要..
所以如果复杂对象的比较不能以简单的标准方式完成,最好留给程序员去实现适用于这种情况的规则..
那么语言可以实现什么样的比较至少是有用和可靠的。比较两个对象引用是否相等,这将允许进行验证,如 obj == null
或 obj == this
或者如果 obja == objb
所以我们至少可以知道 object/reference 我们在说什么..
所以总而言之,原始类型总是通过它们的值进行比较,复杂类型通过它们的引用进行比较,这就是大多数语言所做的,而不是受到 c++ 或其他任何东西的启发 'the rules of the game'
我知道在 SO 上有类似的问题,但其中 none 提供了我正在寻找的答案。
在JavaScript中,如果执行以下操作,结果将为假:
我知道这与 JavaScript 在规范中的定义有关,但为什么会这样?这是违反直觉的。
如果 ("string" === "string")
结果为 true
,那么为什么 ({ } === { })
不为真?
我在某处看到平等算法被设计为类似于 C++ 或 C# 的算法,但这就像发明一种全新的引擎,使用 1/10 的燃料,而不是纯粹为了与其他汽车保持一致而使用它.
为什么 JavaScript 是这样定义的?这个决定背后有什么原因吗?还是只是为了让人看到它在做这件事?
字符串是不可变的,因此具有相同内容的两个字符串在功能上是无法区分的。
但是对象和数组是可以修改的,因此仅仅因为它们在某个特定时间碰巧具有相同的内容并不意味着它们是相同的。你可以修改它们,然后它们就会不同。
另一种说法是,如果 obj1 == obj2
为真,那么当您执行 obj1.x = 1
时,它也会更改 obj2.x
。
{}
是在javascript中创建对象的文字。那就是你可以替换
var obj = new Object();
和
var obj = {};
所以任何时候你使用 {}
你都在创建一个新对象。
您提到的行 {} == {}
创建了两个不同的对象,并且都没有属性。相同地,它们是相同的,就像如果你有 equals(obj1, obj2)
方法比较 obj1 和 obj2 的属性,如果两者的所有属性值都相同,它应该 return 为真。
但是 ==
运算符不会检查属性。它检查两个对象是否指向相同的 object/reference.
而
var obj1 = {};
obj2 = obj1;
console.log(obj2 == obj1); //returns true
return为真,因为 obj1 和 obj2 指向相同的引用。
最后,关于字符串 "abc" == "abc"
,此处 ==
运算符查找实际的字符串内容,并根据它 returns true/false。
因为 javascript 中的字符串即使是一个对象也被认为是基元,就像整数或布尔值一样,并且它们总是按值进行比较,因为这就是基元,一个简单的原子值.. 所以 "string" == "string"
, 1 = 1
和 true == true
,
但是对象是复杂的类型,它们是基元的集合,比较那个集合的规则,不能简化为标准,是{name:'a',address:'b',phone:'c'} != {name:'a',address:'b'}
因为没有相同数量的属性吗?那么在那种情况下会 {name:'x',address:'y'} == {name:'a',address'b'}
吗?它们具有相同的属性,但具有不同的值,或者使其更复杂 {name:'x',address'y'} == {address:'y',name:'c'}
..顺序是否重要..
所以如果复杂对象的比较不能以简单的标准方式完成,最好留给程序员去实现适用于这种情况的规则..
那么语言可以实现什么样的比较至少是有用和可靠的。比较两个对象引用是否相等,这将允许进行验证,如 obj == null
或 obj == this
或者如果 obja == objb
所以我们至少可以知道 object/reference 我们在说什么..
所以总而言之,原始类型总是通过它们的值进行比较,复杂类型通过它们的引用进行比较,这就是大多数语言所做的,而不是受到 c++ 或其他任何东西的启发 'the rules of the game'