处理对象

JavaScript 是基于简单的基于对象的范例而设计的。对象是 properties 的集合,属性是名称(或键)和值之间的关联。属性的值可以是一个函数,在这种情况下,该属性称为 method

¥JavaScript is designed on a simple object-based paradigm. An object is a collection of properties, and a property is an association between a name (or key) and a value. A property's value can be a function, in which case the property is known as a method.

JavaScript 中的对象与许多其他编程语言中的对象一样,可以与现实生活中的对象进行比较。在 JavaScript 中,对象是一个独立的实体,具有属性和类型。例如,将其与杯子进行比较。杯子是一个对象,具有属性。杯子有颜色、设计、重量、材质等。同样,JavaScript 对象也可以有属性,这些属性定义了它们的特性。

¥Objects in JavaScript, just as in many other programming languages, can be compared to objects in real life. In JavaScript, an object is a standalone entity, with properties and type. Compare it with a cup, for example. A cup is an object, with properties. A cup has a color, a design, weight, a material it is made of, etc. The same way, JavaScript objects can have properties, which define their characteristics.

除了浏览器中预定义的对象之外,你还可以定义自己的对象。本章介绍如何使用对象、属性和方法,以及如何创建自己的对象。

¥In addition to objects that are predefined in the browser, you can define your own objects. This chapter describes how to use objects, properties, and methods, and how to create your own objects.

创建新对象

¥Creating new objects

你可以使用 对象初始值设定项 创建对象。或者,你可以首先创建构造函数,然后通过使用 new 运算符调用该函数来实例化对象。

¥You can create an object using an object initializer. Alternatively, you can first create a constructor function and then instantiate an object by invoking that function with the new operator.

使用对象初始值设定项

¥Using object initializers

对象初始值设定项也称为对象文字。"对象初始值设定项" 与 C++ 使用的术语一致。

¥Object initializers are also called object literals. "Object initializer" is consistent with the terminology used by C++.

使用对象初始值设定项的对象的语法是:

¥The syntax for an object using an object initializer is:

js
const obj = {
  property1: value1, // property name may be an identifier
  2: value2, // or a number
  "property n": value3, // or a string
};

冒号之前的每个属性名称都是一个标识符(名称、数字或字符串文字),每个 valueN 都是一个表达式,其值分配给属性名称。属性名称也可以是表达式;计算出的键需要用方括号括起来。对象初始值设定项 参考包含更详细的语法解释。

¥Each property name before colons is an identifier (either a name, a number, or a string literal), and each valueN is an expression whose value is assigned to the property name. The property name can also be an expression; computed keys need to be wrapped in square brackets. The object initializer reference contains a more detailed explanation of the syntax.

在此示例中,新创建的对象被分配给变量 obj — 这是可选的。如果不需要在其他地方引用该对象,则不需要将其分配给变量。(请注意,如果对象出现在预期语句的位置,则可能需要将对象字面量括在括号中,以免将字面量与块语句混淆。)

¥In this example, the newly created object is assigned to a variable obj — this is optional. If you do not need to refer to this object elsewhere, you do not need to assign it to a variable. (Note that you may need to wrap the object literal in parentheses if the object appears where a statement is expected, so as not to have the literal be confused with a block statement.)

对象初始值设定项是表达式,并且每个对象初始值设定项都会在执行它出现的语句时创建一个新对象。相同的对象初始值设定项创建不同的对象,这些对象相互比较时不相等。

¥Object initializers are expressions, and each object initializer results in a new object being created whenever the statement in which it appears is executed. Identical object initializers create distinct objects that do not compare to each other as equal.

当且仅当表达式 cond 为 true 时,以下语句创建一个对象并将其分配给变量 x

¥The following statement creates an object and assigns it to the variable x if and only if the expression cond is true:

js
let x;
if (cond) {
  x = { greeting: "hi there" };
}

以下示例创建具有三个属性的 myHonda。请注意,engine 属性也是一个具有自己属性的对象。

¥The following example creates myHonda with three properties. Note that the engine property is also an object with its own properties.

js
const myHonda = {
  color: "red",
  wheels: 4,
  engine: { cylinders: 4, size: 2.2 },
};

使用初始值设定项创建的对象称为普通对象,因为它们是 Object 的实例,而不是任何其他对象类型。某些对象类型具有特殊的初始化语法,例如 数组初始值设定项正则表达式文字

¥Objects created with initializers are called plain objects, because they are instances of Object, but not any other object type. Some object types have special initializer syntaxes — for example, array initializers and regex literals.

使用构造函数

¥Using a constructor function

或者,你可以通过以下两个步骤创建一个对象:

¥Alternatively, you can create an object with these two steps:

  1. 通过编写构造函数来定义对象类型。使用大写首字母是一个强有力的惯例,并且有充分的理由。
  2. 使用 new 创建对象的实例。

要定义对象类型,请为该对象类型创建一个指定其名称、属性和方法的函数。例如,假设你要创建汽车的对象类型。你希望这种类型的对象被称为 Car,并且你希望它具有品牌、型号和年份属性。为此,你需要编写以下函数:

¥To define an object type, create a function for the object type that specifies its name, properties, and methods. For example, suppose you want to create an object type for cars. You want this type of object to be called Car, and you want it to have properties for make, model, and year. To do this, you would write the following function:

js
function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}

请注意,使用 this 根据传递给函数的值将值分配给对象的属性。

¥Notice the use of this to assign values to the object's properties based on the values passed to the function.

现在你可以创建一个名为 myCar 的对象,如下所示:

¥Now you can create an object called myCar as follows:

js
const myCar = new Car("Eagle", "Talon TSi", 1993);

该语句创建 myCar 并为其属性分配指定的值。那么 myCar.make 的值就是字符串 "Eagle"myCar.model 就是字符串 "Talon TSi"myCar.year 就是整数 1993,以此类推。参数和参数的顺序应该相同。

¥This statement creates myCar and assigns it the specified values for its properties. Then the value of myCar.make is the string "Eagle", myCar.model is the string "Talon TSi", myCar.year is the integer 1993, and so on. The order of arguments and parameters should be the same.

你可以通过调用 new 创建任意数量的 Car 对象。例如,

¥You can create any number of Car objects by calls to new. For example,

js
const kenscar = new Car("Nissan", "300ZX", 1992);
const vpgscar = new Car("Mazda", "Miata", 1990);

一个对象可以拥有一个属性,该属性本身就是另一个对象。例如,假设你定义一个名为 Person 的对象,如下所示:

¥An object can have a property that is itself another object. For example, suppose you define an object called Person as follows:

js
function Person(name, age, sex) {
  this.name = name;
  this.age = age;
  this.sex = sex;
}

然后实例化两个新的 Person 对象,如下所示:

¥and then instantiate two new Person objects as follows:

js
const rand = new Person("Rand McKinnon", 33, "M");
const ken = new Person("Ken Jones", 39, "M");

然后,你可以重写 Car 的定义以包含采用 Person 对象的 owner 属性,如下所示:

¥Then, you can rewrite the definition of Car to include an owner property that takes a Person object, as follows:

js
function Car(make, model, year, owner) {
  this.make = make;
  this.model = model;
  this.year = year;
  this.owner = owner;
}

要实例化新对象,请使用以下命令:

¥To instantiate the new objects, you then use the following:

js
const car1 = new Car("Eagle", "Talon TSi", 1993, rand);
const car2 = new Car("Nissan", "300ZX", 1992, ken);

请注意,上面的语句在创建新对象时没有传递文字字符串或整数值,而是传递对象 randken 作为所有者的参数。那么如果你想找出 car2 的所有者的名字,你可以访问以下属性:

¥Notice that instead of passing a literal string or integer value when creating the new objects, the above statements pass the objects rand and ken as the arguments for the owners. Then if you want to find out the name of the owner of car2, you can access the following property:

js
car2.owner.name;

你始终可以向先前定义的对象添加属性。例如,声明

¥You can always add a property to a previously defined object. For example, the statement

js
car1.color = "black";

将属性 color 添加到 car1,并为其分配值 "black"。但是,这不会影响任何其他对象。要将新属性添加到同一类型的所有对象,你必须将该属性添加到 Car 对象类型的定义中。

¥adds a property color to car1, and assigns it a value of "black". However, this does not affect any other objects. To add the new property to all objects of the same type, you have to add the property to the definition of the Car object type.

你还可以使用 class 语法而不是 function 语法来定义构造函数。有关详细信息,请参阅 班主任

¥You can also use the class syntax instead of the function syntax to define a constructor function. For more information, see the class guide.

使用 Object.create() 方法

¥Using the Object.create() method

还可以使用 Object.create() 方法创建对象。此方法非常有用,因为它允许你为要创建的对象选择 prototype 对象,而无需定义构造函数。

¥Objects can also be created using the Object.create() method. This method can be very useful, because it allows you to choose the prototype object for the object you want to create, without having to define a constructor function.

js
// Animal properties and method encapsulation
const Animal = {
  type: "Invertebrates", // Default value of properties
  displayType() {
    // Method which will display type of Animal
    console.log(this.type);
  },
};

// Create new animal type called animal1
const animal1 = Object.create(Animal);
animal1.displayType(); // Logs: Invertebrates

// Create new animal type called fish
const fish = Object.create(Animal);
fish.type = "Fishes";
fish.displayType(); // Logs: Fishes

对象和属性

¥Objects and properties

JavaScript 对象具有与其关联的属性。对象属性与变量基本相同,只不过它们与对象关联,而不是与 scopes 关联。对象的属性定义了对象的特性。

¥A JavaScript object has properties associated with it. Object properties are basically the same as variables, except that they are associated with objects, not scopes. The properties of an object define the characteristics of the object.

例如,此示例创建一个名为 myCar 的对象,其属性名为 makemodelyear,其值设置为 "Ford""Mustang"1969

¥For example, this example creates an object named myCar, with properties named make, model, and year, with their values set to "Ford", "Mustang", and 1969:

js
const myCar = {
  make: "Ford",
  model: "Mustang",
  year: 1969,
};

与 JavaScript 变量一样,属性名称区分大小写。属性名称只能是字符串或符号 - 所有键都是 转换为字符串,除非它们是符号。事实上,数组索引 是带有包含整数的字符串键的属性。

¥Like JavaScript variables, property names are case sensitive. Property names can only be strings or Symbols — all keys are converted to strings unless they are Symbols. Array indices are, in fact, properties with string keys that contain integers.

访问属性

¥Accessing properties

你可以通过对象的属性名称来访问对象的属性。属性访问器 有两种语法:点表示法和括号表示法。例如,你可以按如下方式访问 myCar 对象的属性:

¥You can access a property of an object by its property name. Property accessors come in two syntaxes: dot notation and bracket notation. For example, you could access the properties of the myCar object as follows:

js
// Dot notation
myCar.make = "Ford";
myCar.model = "Mustang";
myCar.year = 1969;

// Bracket notation
myCar["make"] = "Ford";
myCar["model"] = "Mustang";
myCar["year"] = 1969;

对象属性名称可以是任何 JavaScript 字符串或 symbol,包括空字符串。但是,你不能使用点符号来访问名称不是有效 JavaScript 标识符的属性。例如,包含空格或连字符、以数字开头或保存在变量内的属性名称只能使用方括号表示法进行访问。当要动态确定属性名称(即直到运行时才能确定)时,此表示法也非常有用。示例如下:

¥An object property name can be any JavaScript string or symbol, including an empty string. However, you cannot use dot notation to access a property whose name is not a valid JavaScript identifier. For example, a property name that has a space or a hyphen, that starts with a number, or that is held inside a variable can only be accessed using the bracket notation. This notation is also very useful when property names are to be dynamically determined, i.e. not determinable until runtime. Examples are as follows:

js
const myObj = {};
const str = "myString";
const rand = Math.random();
const anotherObj = {};

// Create additional properties on myObj
myObj.type = "Dot syntax for a key named type";
myObj["date created"] = "This key has a space";
myObj[str] = "This key is in variable str";
myObj[rand] = "A random number is the key here";
myObj[anotherObj] = "This key is object anotherObj";
myObj[""] = "This key is an empty string";

console.log(myObj);
// {
//   type: 'Dot syntax for a key named type',
//   'date created': 'This key has a space',
//   myString: 'This key is in variable str',
//   '0.6398914448618778': 'A random number is the key here',
//   '[object Object]': 'This key is object anotherObj',
//   '': 'This key is an empty string'
// }
console.log(myObj.myString); // 'This key is in variable str'

在上面的代码中,键 anotherObj 是一个对象,它既不是字符串也不是符号。当它被添加到 myObj 时,JavaScript 调用 anotherObjtoString() 方法,并使用结果字符串作为新的键。

¥In the above code, the key anotherObj is an object, which is neither a string nor a symbol. When it is added to the myObj, JavaScript calls the toString() method of anotherObj, and use the resulting string as the new key.

你还可以使用存储在变量中的字符串值访问属性。变量必须以括号表示法传递。在上面的示例中,变量 str 保存着 "myString",而 "myString" 是属性名称。因此,myObj.str 将返回为未定义。

¥You can also access properties with a string value stored in a variable. The variable must be passed in bracket notation. In the example above, the variable str held "myString" and it is "myString" that is the property name. Therefore, myObj.str will return as undefined.

js
str = "myString";
myObj[str] = "This key is in variable str";

console.log(myObj.str); // undefined

console.log(myObj[str]); // 'This key is in variable str'
console.log(myObj.myString); // 'This key is in variable str'

这允许访问运行时确定的任何属性:

¥This allows accessing any property as determined at runtime:

js
let propertyName = "make";
myCar[propertyName] = "Ford";

// access different properties by changing the contents of the variable
propertyName = "model";
myCar[propertyName] = "Mustang";

console.log(myCar); // { make: 'Ford', model: 'Mustang' }

但是,请注意使用方括号来访问其名称由外部输入指定的属性。这可能会使你的代码容易受到 对象注入攻击 的影响。

¥However, beware of using square brackets to access properties whose names are given by external input. This may make your code susceptible to object injection attacks.

对象不存在的属性具有值 undefined(而不是 null)。

¥Nonexistent properties of an object have value undefined (and not null).

js
myCar.nonexistentProperty; // undefined

枚举属性

¥Enumerating properties

列出/遍历对象属性的原生方法有以下三种:

¥There are three native ways to list/traverse object properties:

  • for...in 循环。该方法遍历对象的所有可枚举字符串属性及其原型链。
  • Object.keys()。该方法返回一个数组,其中仅包含对象 myObj 中可枚举的自身字符串属性名称("keys"),而不包含原型链中的属性名称。
  • Object.getOwnPropertyNames()。该方法返回一个数组,其中包含对象 myObj 中所有自己的字符串属性名称,无论它们是否可枚举。

你可以使用带有 for...in 的括号表示法来迭代对象的所有可枚举属性。为了说明其工作原理,当你将对象和对象名称作为参数传递给函数时,以下函数将显示对象的属性:

¥You can use the bracket notation with for...in to iterate over all the enumerable properties of an object. To illustrate how this works, the following function displays the properties of the object when you pass the object and the object's name as arguments to the function:

js
function showProps(obj, objName) {
  let result = "";
  for (const i in obj) {
    // Object.hasOwn() is used to exclude properties from the object's
    // prototype chain and only show "own properties"
    if (Object.hasOwn(obj, i)) {
      result += `${objName}.${i} = ${obj[i]}\n`;
    }
  }
  console.log(result);
}

术语 "自有属性" 指的是对象的属性,但不包括原型链的属性。因此,函数调用 showProps(myCar, 'myCar') 将打印以下内容:

¥The term "own property" refers to the properties of the object, but excluding those of the prototype chain. So, the function call showProps(myCar, 'myCar') would print the following:

myCar.make = Ford
myCar.model = Mustang
myCar.year = 1969

上式等价于:

¥The above is equivalent to:

js
function showProps(obj, objName) {
  let result = "";
  Object.keys(obj).forEach((i) => {
    result += `${objName}.${i} = ${obj[i]}\n`;
  });
  console.log(result);
}

没有本地方法来列出继承的不可枚举属性。然而,这可以通过以下函数来实现:

¥There is no native way to list inherited non-enumerable properties. However, this can be achieved with the following function:

js
function listAllProperties(myObj) {
  let objectToInspect = myObj;
  let result = [];

  while (objectToInspect !== null) {
    result = result.concat(Object.getOwnPropertyNames(objectToInspect));
    objectToInspect = Object.getPrototypeOf(objectToInspect);
  }

  return result;
}

欲了解更多信息,请参阅 可枚举性和属性所有权

¥For more information, see Enumerability and ownership of properties.

删除属性

¥Deleting properties

你可以使用 delete 运算符删除非继承属性。以下代码显示如何删除属性。

¥You can remove a non-inherited property using the delete operator. The following code shows how to remove a property.

js
// Creates a new object, myobj, with two properties, a and b.
const myobj = new Object();
myobj.a = 5;
myobj.b = 12;

// Removes the a property, leaving myobj with only the b property.
delete myobj.a;
console.log("a" in myobj); // false

遗产

¥Inheritance

JavaScript 中的所有对象都至少从一个其他对象继承。继承的对象称为原型,继承的属性可以在构造函数的 prototype 对象中找到。请参阅 继承和原型链 了解更多信息。

¥All objects in JavaScript inherit from at least one other object. The object being inherited from is known as the prototype, and the inherited properties can be found in the prototype object of the constructor. See Inheritance and the prototype chain for more information.

为一种类型的所有对象定义属性

¥Defining properties for all objects of one type

你可以使用 prototype 属性向通过某个 构造函数 创建的所有对象添加属性。这定义了一个由指定类型的所有对象共享的属性,而不仅仅是该对象的一个实例。以下代码将 color 属性添加到 Car 类型的所有对象,然后从实例 car1 读取该属性的值。

¥You can add a property to all objects created through a certain constructor using the prototype property. This defines a property that is shared by all objects of the specified type, rather than by just one instance of the object. The following code adds a color property to all objects of type Car, and then reads the property's value from an instance car1.

js
Car.prototype.color = "red";
console.log(car1.color); // "red"

定义方法

¥Defining methods

方法是与对象关联的函数,或者换句话说,方法是作为函数的对象的属性。方法的定义方式与普通函数的定义方式相同,只不过它们必须被指定为对象的属性。另请参阅 方法定义 了解更多详细信息。一个例子是:

¥A method is a function associated with an object, or, put differently, a method is a property of an object that is a function. Methods are defined the way normal functions are defined, except that they have to be assigned as the property of an object. See also method definitions for more details. An example is:

js
objectName.methodName = functionName;

const myObj = {
  myMethod: function (params) {
    // do something
  },

  // this works too!
  myOtherMethod(params) {
    // do something else
  },
};

其中 objectName 是现有对象,methodName 是你分配给方法的名称,functionName 是函数的名称。

¥where objectName is an existing object, methodName is the name you are assigning to the method, and functionName is the name of the function.

然后,你可以在对象的上下文中调用该方法,如下所示:

¥You can then call the method in the context of the object as follows:

js
objectName.methodName(params);

方法通常定义在构造函数的 prototype 对象上,以便同一类型的所有对象共享相同的方法。例如,你可以定义一个函数,用于格式化并显示先前定义的 Car 对象的属性。

¥Methods are typically defined on the prototype object of the constructor, so that all objects of the same type share the same method. For example, you can define a function that formats and displays the properties of the previously-defined Car objects.

js
Car.prototype.displayCar = function () {
  const result = `A Beautiful ${this.year} ${this.make} ${this.model}`;
  console.log(result);
};

请注意使用 this 来引用该方法所属的对象。然后你可以为每个对象调用 displayCar 方法,如下所示:

¥Notice the use of this to refer to the object to which the method belongs. Then you can call the displayCar method for each of the objects as follows:

js
car1.displayCar();
car2.displayCar();

使用 this 作为对象引用

¥Using this for object references

JavaScript 有一个特殊的关键字 this,你可以在方法中使用它来引用当前对象。例如,假设你有 2 个对象,ManagerIntern。每个对象都有自己的 nameagejob。在函数 sayHi() 中,注意 this.name 的使用。当添加到 2 个对象时,相同的函数将打印消息及其所附加的相应对象的名称。

¥JavaScript has a special keyword, this, that you can use within a method to refer to the current object. For example, suppose you have 2 objects, Manager and Intern. Each object has its own name, age and job. In the function sayHi(), notice the use of this.name. When added to the 2 objects, the same function will print the message with the name of the respective object it's attached to.

js
const Manager = {
  name: "Karina",
  age: 27,
  job: "Software Engineer",
};
const Intern = {
  name: "Tyrone",
  age: 21,
  job: "Software Engineer Intern",
};

function sayHi() {
  console.log(`Hello, my name is ${this.name}`);
}

// add sayHi function to both objects
Manager.sayHi = sayHi;
Intern.sayHi = sayHi;

Manager.sayHi(); // Hello, my name is Karina
Intern.sayHi(); // Hello, my name is Tyrone

this 是函数调用的 "隐藏参数",通过在调用的函数之前指定对象来传入。例如,在 Manager.sayHi() 中,thisManager 对象,因为 Manager 位于函数 sayHi() 之前。如果从另一个对象访问相同的函数,this 也会改变。如果使用其他方法调用该函数,例如 Function.prototype.call()Reflect.apply(),则可以显式传递 this 的值作为参数。

¥this is a "hidden parameter" of a function call that's passed in by specifying the object before the function that was called. For example, in Manager.sayHi(), this is the Manager object, because Manager comes before the function sayHi(). If you access the same function from another object, this will change as well. If you use other methods to call the function, like Function.prototype.call() or Reflect.apply(), you can explicitly pass the value of this as an argument.

定义 getter 和 setter

¥Defining getters and setters

getter 是与属性关联的函数,用于获取特定属性的值。setter 是与属性关联的函数,用于设置特定属性的值。它们一起可以间接代表属性的价值。

¥A getter is a function associated with a property that gets the value of a specific property. A setter is a function associated with a property that sets the value of a specific property. Together, they can indirectly represent the value of a property.

Getter 和 Setter 可以是

¥Getters and setters can be either

对象初始值设定项 中,getter 和 setter 的定义与常规 methods 类似,但以关键字 getset 为前缀。getter 方法不能期望有一个参数,而 setter 方法则期望有一个参数(要设置的新值)。例如:

¥Within object initializers, getters and setters are defined like regular methods, but prefixed with the keywords get or set. The getter method must not expect a parameter, while the setter method expects exactly one parameter (the new value to set). For instance:

js
const myObj = {
  a: 7,
  get b() {
    return this.a + 1;
  },
  set c(x) {
    this.a = x / 2;
  },
};

console.log(myObj.a); // 7
console.log(myObj.b); // 8, returned from the get b() method
myObj.c = 50; // Calls the set c(x) method
console.log(myObj.a); // 25

myObj 对象的属性是:

¥The myObj object's properties are:

  • myObj.a — 一个数字
  • myObj.b — 返回 myObj.a 加 1 的 getter
  • myObj.c — 一个设置器,将 myObj.a 的值设置为 myObj.c 值的一半

Getter 和 Setter 也可以在创建后随时使用 Object.defineProperties() 方法添加到对象中。此方法的第一个参数是要在其上定义 getter 或 setter 的对象。第二个参数是一个对象,其属性名称是 getter 或 setter 名称,其属性值是用于定义 getter 或 setter 函数的对象。下面的示例定义了与上一个示例中使用的相同的 getter 和 setter:

¥Getters and setters can also be added to an object at any time after creation using the Object.defineProperties() method. This method's first parameter is the object on which you want to define the getter or setter. The second parameter is an object whose property names are the getter or setter names, and whose property values are objects for defining the getter or setter functions. Here's an example that defines the same getter and setter used in the previous example:

js
const myObj = { a: 0 };

Object.defineProperties(myObj, {
  b: {
    get() {
      return this.a + 1;
    },
  },
  c: {
    set(x) {
      this.a = x / 2;
    },
  },
});

myObj.c = 10; // Runs the setter, which assigns 10 / 2 (5) to the 'a' property
console.log(myObj.b); // Runs the getter, which yields a + 1 or 6

选择两种形式中的哪一种取决于你的编程风格和手头的任务。如果可以更改原始对象的定义,则可能会通过原始初始值设定项定义 getter 和 setter。这种形式更加紧凑、自然。但是,如果你稍后需要添加 getter 和 setter(可能是因为你没有编写特定对象),那么第二种形式是唯一可能的形式。第二种形式更好地代表了 JavaScript 的动态特性,但它会使代码难以阅读和理解。

¥Which of the two forms to choose depends on your programming style and task at hand. If you can change the definition of the original object, you will probably define getters and setters through the original initializer. This form is more compact and natural. However, if you need to add getters and setters later — maybe because you did not write the particular object — then the second form is the only possible form. The second form better represents the dynamic nature of JavaScript, but it can make the code hard to read and understand.

比较对象

¥Comparing objects

在 JavaScript 中,对象是引用类型。两个不同的对象永远不会相等,即使它们具有相同的属性。只有将相同的对象引用与其自身进行比较才会产生 true。

¥In JavaScript, objects are a reference type. Two distinct objects are never equal, even if they have the same properties. Only comparing the same object reference with itself yields true.

js
// Two variables, two distinct objects with the same properties
const fruit = { name: "apple" };
const fruitbear = { name: "apple" };

fruit == fruitbear; // return false
fruit === fruitbear; // return false
js
// Two variables, a single object
const fruit = { name: "apple" };
const fruitbear = fruit; // Assign fruit object reference to fruitbear

// Here fruit and fruitbear are pointing to same object
fruit == fruitbear; // return true
fruit === fruitbear; // return true

fruit.name = "grape";
console.log(fruitbear); // { name: "grape" }; not { name: "apple" }

有关比较运算符的更多信息,请参阅 相等运算符

¥For more information about comparison operators, see equality operators.

也可以看看