JavaScript对象身份

13

在JavaScript中,对象具有独特的身份。每个通过构造函数或字面量表达式创建的对象都与其他对象不同。

这背后的原因是什么?

{}==={}//output:false

它们为什么会被不同对待?是什么使它们彼此不同?


1
这就是大多数面向对象语言的工作方式。两个对象是不相等的,即使它们具有相同的类型和所有私有和公共变量具有相同的值,它们仍然是两个独立的对象,因此它们不相等。 - Philipp
2
不要在Stack Overflow上质疑编程语言的设计。你永远不知道语言作者当时的想法。 - John Dvorak
1
@JanDvorak:但是许多语言的作者确实在公开场合讨论了他们的想法,或者写了关于语言设计的书籍。我认为这个问题是合理的,尽管答案可能更加通用(跨语言)。 - Bergi
1
考虑“相等”和“相同”的概念并理解它们的区别是很有用的。两个对象可以是相等的(它们具有相同的内容),但它们不是同一个,即它们不是相同的。===运算符检查身份,而不是相等性。因此,{}==={}会创建2个对象,结果为false。 - i2B
@JohnDvorak 我认为他并不质疑他们这样做的理由,他只是在字面上问为什么 {} 不等于 {}。我没有意识到对象字面量 {} 本质上是 new Object(),这可能是他正在寻找的类型。 - Michael Ward
@JohnDvorak:我认为语言设计者的推理往往对如何使用语言产生深远的影响。或者,也许,如何使用语言的事实可以无害地被“错误地”误认为是作者的意图,就像人们说“我们的肺没有‘设计’用来做这个、那个或另一个事情”一样。如果你相信进化论,或肺没有任何“设计”去做任何事情,它们只是进化而来。但语法简写是清晰、简洁和有用的。虽然,我必须承认,太多的语法糖可能会导致分号癌。 :) - Nobody Tells The Truth
6个回答

12

{} 创建了一个新的对象。

当你试图比较两个独立的对象(引用)时,它们永远不会相等。

简单来说:

var a = {};  // New object, new reference in memory, stored in `a`
var b = {};  // New object, new reference in memory, stored in `b`

a === b;  // Compares (different) references in memory

如果有帮助的话,{}new Object()的“快捷方式”,更明确地说:

var a = new Object();
var b = new Object();

a === b;  // Still false

也许new的明确性有助于你理解比较不同对象之间的差异。
另一方面,如果引用指向相同的对象,则它们可以是相等的。例如:
var a = {};
var b = a;

a === b;  // TRUE

@delnan:“它们为什么被不同对待?是什么使它们彼此不同?”- 我的理由是它们是不同的引用。 - Ian

6

它们是不同的对象实例,可以独立进行修改。即使它们(当前)看起来相似,它们也不相同。有时候通过比较它们的(属性)值可能是有用的,但在有状态编程语言中,对象等价通常是它们的身份。


1
但是它们之间有什么不同呢?因为这些实例共享相同的属性和方法。有何区别? - Maizere Pathak.Nepal
2
如果您将它们中的一个传递给修改它的函数,则另一个不会更改。我只知道(默认)按值相等来自无状态编程语言。 - Bergi

3
这个问题很久了,但我认为实际解决方案在给出的答案中并没有清晰地呈现出来。
它们为什么会被不同对待?是什么使它们彼此不同?
我理解你的痛苦,因为互联网上的许多来源都没有直接说明事实: 对象(复杂的JS类型 => 对象、数组和函数)变量仅存储引用(内存中实例的地址)作为它们的值。对象身份由引用身份识别。
你期望对象内部有类似于ID或引用的东西,可以用来区分它们(也许在幕后透明地完成)。但每次实例化一个对象时,都会在内存中创建一个新实例,只有对它的引用存储在变量中。
因此,当===运算符的描述说它比较值时,它实际上是比较引用(而不是属性及其值),只有指向完全相同的对象时才相等。
这篇文章详细解释了JavaScript中的值与引用:https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0 敬礼 Michael

2

它们的不同在这种情况下非常重要:

a={}; 
b={}; 
a.some_prop = 3;

此时,您显然知道b.some_prop将是未定义的。

因此, == === 运算符允许您确保您不会更改某个对象的属性,而您不希望更改。


0

这两个对象都是在内存中作为单独的实体创建的。准确地说,这两个对象都是在堆上作为单独的实体创建的(JavaScript 引擎使用堆和栈 内存模型 来管理运行脚本)。因此,这两个对象可能看起来相同(结构、属性等),但在底层它们在内存中有两个不同的地址。

这里有一些直觉。想象一个所有房子看起来都一样的新社区。你决定建造另外两座完全相同的建筑物,在完成建设后,这两座建筑物看起来完全相同,甚至“坐”在一起,但它们仍然不是同一座建筑物。它们有两个不同的地址。


0

我认为最简单的答案是“它们存储在内存中的不同位置”。虽然在隐藏指针的语言中并不总是清晰(如果您了解C、C++或汇编语言,您就知道指针是什么,否则学习低级语言是有用的),通过将每个“对象”都变成指针,实际上每个“对象”都是指向内存中对象存在的位置的指针。在某些情况下,两个变量将指向内存中的相同位置。在其他情况下,它们将指向具有类似或相同内容的不同内存位置。这就像有两个不同的URL,每个URL都指向相同的页面。网页彼此相等,但URL不同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接