对象类型

js/object2026-08-24 19:46:25

在 JavaScript 中,大多数事物都是 对象,从作为核心功能的字符串和数组,到建立在 JavaScript 之上的浏览器 API 。你甚至可以自己创建对象,将相关的函数和变量高效地封装打包成便捷的数据容器。

在 JavaScript 中对象是一种 引用类型。两个独立声明的对象永远也不会相等,即使他们有相同的属性,只有在比较一个对象和这个对象的引用时,才会返回 true。

本词条探讨的是对象这个数据类型。关于内置全局变量 Object,参见内置全局变量词条的 Object。

关于 Array 等其他常用内置全局对象,参见 内置全局变量 词条。
关于原始类型包装对象 String 等,参见 内置全局变量 词条。
关于 Function 对象和 Class 对象,参见 函数和类 词条。

对象的属性

一个 JavaScript 对象有很多 属性。一个对象的属性可以被解释成一个附加到对象上的变量。对象的属性和普通的 JavaScript 变量基本没什么区别,仅仅是属性属于某个对象。属性定义了对象的特征。

一个对象的属性名可以是任何有效的 JavaScript 字符串或者 Symbol,或者可以被转换为字符串的任何类型,包括空字符串。

一个对象的属性可以是任何类型的变量,所以也可以是另一个对象,甚至可以是对象自身。

访问和设置对象的属性

可以通过点符号 (.) 或者方括号 ([]) 来访问或者一个对象的属性。和其他 JavaScript 变量一样,对象的名字和属性的名字都是大小写敏感的。

myCar.make = "Ford";
myCar["make"] = "Ford";

对象中未赋值的属性的值为 undefined(而不是 null)。

myCar.noProperty; // undefined

然而,一个属性的名称如果不是一个有效的 JavaScript 标识符(例如,Symbol、一个由空格或连字符,或者以数字开头的属性名),就只能通过方括号标记访问。

动态计算属性名

方括号标记在属性名称是动态判定(属性名只有到运行时才能判定)时非常有用。

var propertyName = "make";
myCar[propertyName] = "Ford";

枚举一个对象的属性

从 ECMAScript 5 开始,有三种原生的方法用于列出或枚举对象的属性:

  • for...in 循环:该方法依次访问一个对象及其原型链中所有可枚举的属性。

  • Object.keys(o) 静态方法方法返回对象 o 自身包含(不包括原型中)的所有可枚举属性的名称的数组。Object.values() 静态方法返回一个给定对象的自有可枚举字符串键属性值组成的数组。Object.entries() 返回一个数组,其元素是直接在 object 上找到相应的可枚举字符串键属性的键值对数组。

  • Object.getOwnPropertyNames(o) 方法返回对象 o 自身包含(不包括原型中)的所有属性 (无论是否可枚举) 的名称的数组。不包含对象的 Symbol 属性,只包含字符串属性。Object.getOwnPropertySymbols(o) 方法返回对象 o 自身包含(不包括原型中)的 Symbol 属性 (无论是否可枚举) 的名称的数组。

你可以在 for...in 语句中使用方括号标记以枚举一个对象的所有属性。

for (var i in obj) {
  // obj[i]
}

创建对象

JavaScript 拥有一系列预定义的对象。另外,你可以创建你自己的对象。

通过字面值创建对象

可以通过 对象初始化器 创建对象。使用对象初始化器也被称作 通过字面值创建对象。对象初始化器与 C++ 术语相一致。

通过对象初始化器创建对象的语法如下:

var obj = {
  property_1: value_1, // property_# 可以是一个标识符...
  2: value_2, // 或一个数字...
  ["property" + 3]: value_3, //  或一个可计算的 key 名...
  // ...,
  "property n": value_n,
}; // 或一个字符串

这里 obj 是新对象的名称,每一个 property_i 是一个标识符(可以是一个名称、数字或字符串字面量),并且每个 value_i 是一个其值将被赋予 property_i 的表达式。obj 与赋值是可选的;如果你不需要在其他地方引用对象,你就不需要将它赋给一个变量。(注意在接受一条语句的地方,你可能需要将对象字面量括在括号里,从而避免将字面量与块语句相混淆)

如果一个对象是通过在顶级脚本的对象初始化器创建的,则 JavaScript 在每次遇到包含该对象字面量的表达式时都会创建对象。同样的,在函数中的初始化器在每次函数调用时也会被创建。

使用构造函数创建对象

作为另一种方式,你可以通过两步来创建对象:

  • 通过创建一个 构造函数 来定义对象的类型。首字母大写是非常普遍而且很恰当的惯用法。
  • 通过 new 创建 对象实例。

构造函数 是使用 new 关键字调用的函数。当你调用构造函数时,它将:

  • 创建一个新对象
  • 将 this 绑定到新对象,以便你可以在构造函数代码中引用 this
  • 运行构造函数中的代码
  • 返回新对象

为了定义对象类型,为对象类型创建一个函数以声明类型的名称、属性和方法。例如,你想为汽车创建一个类型,并且将这类对象称为 Car ,并且拥有属性 make, model,和 year,你可以创建如下的函数:

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

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

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

使用 Object.create 方法创建对象

对象也可以用 Object.create() 方法创建。该方法非常有用,因为它允许你为创建的对象选择一个 原型对象,而不用定义构造函数。

// Animal properties and method encapsulation
var Animal = {
  type: "Invertebrates", // 属性默认值
  displayType: function () {
    // 用于显示 type 属性的方法
    console.log(this.type);
  },
};

// 创建一种新的动物——animal1
var animal1 = Object.create(Animal);
animal1.displayType(); // Output:Invertebrates

// 创建一种新的动物——Fishes
var fish = Object.create(Animal);
fish.type = "Fishes";
fish.displayType(); // Output:Fishes

对象的继承

所有的 JavaScript 对象至少 继承 于一个对象。被继承的对象被称作 原型,并且继承的属性可通过构造函数的 prototype 对象找到。

你可以通过 prototype 属性为之前定义的对象类型增加属性。这为该类型的所有对象,而不是仅仅一个对象增加了一个属性。下面的代码为所有类型为 Car 的对象增加了 color 属性,然后为对象 car1 的 color 属性赋值:

Car.prototype.color = null;
car1.color = "black";

参考 对象原型与继承 词条。

定义对象的方法

一个 方法 是关联到某个对象的函数,或者简单地说,一个方法是一个值为某个函数的对象属性。定义方法就像定义普通的函数,除了它们必须被赋给对象的某个属性。

var myObj = {
  myMethod: function(params) {
    // ...do something
  }

  // 或者 这样写也可以

  myOtherMethod(params) {
    // ...do something else
  }
};

你可以在对象的上下文中象这样调用方法:

object.methodname(params);

通过 this 引用当前对象

JavaScript 有一个特殊的关键字 this,它可以在方法中使用以指代当前对象。

例如 object.methodname(params),methodname 函数中的 this 代表 object。

注意与构造函数中的 this 区分。

定义 getter 与 setter 方法

你可以为预定义的或用户定义的对象定义 getter 和 setter 方法。

  • 一个 getter 是一个获取某个特定属性的值的方法。
  • 一个 setter 是一个设定某个属性的值的方法。

原则上,getter 和 setter 既可以:

  • 使用 对象初始化器(对象字面量)定义
  • 也可以之后随时使用 getter 和 setter 添加方法(Object.defineProperties()) 添加到任何对象

当使用对象初始化器定义 getter 和 setter 时,只需要在 getter 方法前加 get,在 setter 方法前加 set,当然,getter 方法必须是无参数的,setter 方法只接受一个参数(设置为新值),例如:

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

console.log(o.a); // 7
console.log(o.b); // 8
o.c = 50;
console.log(o.a); // 25

使用 Object.defineProperties 的方法,同样也可以对一个已创建的对象在任何时候为其添加 getter 或 setter 方法。这个方法的第一个参数是你想定义 getter 或 setter 方法的对象,第二个参数是一个对象,这个对象的属性名用作 getter 或 setter 的名字,属性名对应的属性值用作定义 getter 或 setter 方法的函数,下面是一个例子定义了和前面例子一样的 getter 和 setter 方法:

var o = { a: 0 };

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

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

这两种定义方式的选择取决于你的编程风格和手头的工作量。当你定义一个原型准备进行初始化时,可以选择第一种方式,这种方式更简洁和自然。但是,当你需要添加 getter 和 setter 方法——因为并没有编写原型或者特定的对象——使用第二种方式更好。第二种方式可能更能表现 JavaScript 语法的动态特性——但也会使代码变得难以阅读和理解。

删除属性

你可以用 delete 操作符删除一个不是继承而来的属性。

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

//Removes the a property, leaving myobj with only the b property.
delete myobj.a;

如果一个全局变量不是用 var 关键字声明的话,你也可以用 delete 删除它:

g = 17;
delete g;

参考

使用对象
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Working_with_objects

JavaScript 对象入门(JavaScript 对象基础、对象原型、面向对象编程基本概念、JavaScript 中的类)

https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Objects

JavaScript 数据类型和数据结构
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Data_structures

Object 对象
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object

本页目录