JavaScript 对象是 JavaScript 中最基础、最强大的数据结构之一。它是一个无序的键值对集合,其中键(属性名)是字符串(或者是可以转为字符串的值),而值(属性值)可以是任何 JavaScript 数据类型。
1. 什么是 JavaScript 对象?
简单来说,对象是**键值对(key-value pairs)**的集合。其中,键(key)是字符串(或 Symbol),值(value)可以是任何 JavaScript 数据类型,包括:
基本数据类型:字符串、数字、布尔值、null、undefined、Symbol、BigInt 其他对象:包括数组、函数、以及其他自定义对象
1.1 对象的定义
在 JavaScript 中,定义一个对象通常有以下两种方式:
-
字面量方式:
const person = { name: 'John', age: 30, greet: function() { console.log(`Hello, my name is ${this.name}`); } }; -
构造函数方式:
const person = new Object(); person.name = 'John'; person.age = 30; person.greet = function() { console.log(`Hello, my name is ${this.name}`); }; -
**Object.create() **方法: 创建一个新对象,使用现有对象作为新对象的原型。
const proto = {
greet: function() {
console.log("Hello!");
}
};
const obj = Object.create(proto);
obj.name = "王五";
- ES6 的类(Class): 虽然本质上仍然是基于原型继承,但提供了更接近传统面向对象语言的语法
class Person {
constructor(name, age, city) {
this.name = name;
this.age = age;
this.city = city;
}
greet() {
console.log(`你好,我是 ${this.name}`);
}
}
const person2 = new Person("赵六", 40, "广州");
1.2 对象的基本特性
- 无序性:对象的属性在内部是无序的,尽管在某些 JavaScript 引擎中(如 Chrome 的 V8 引擎)会以插入顺序来显示属性,但我们不能依赖这个行为,特别是在设计跨浏览器的应用时。
- 键是字符串类型:即使你给对象的属性使用其他数据类型(如数字或符号),JavaScript 会将它们自动转换为字符串。
- 值可以是任意数据类型:对象的值可以是任意类型,包括其他对象、数组、函数等。
2. 对象的常见操作
2.1 访问对象属性
有两种方式可以访问对象的属性:
-
点语法:
console.log(person.name); // 'John' -
方括号语法(可以动态指定属性名,适用于属性名是动态的情况):
console.log(person['age']); // 30
2.2 添加、修改和删除属性
-
添加属性:
person.job = 'Developer'; -
修改属性:
person.age = 31; -
删除属性:
delete person.job;
-
Object.keys()方法: 返回一个包含对象所有可枚举属性名的数组。const keys = Object.keys(person); keys.forEach(key => console.log(key + ":" + person[key])); -
Object.values()方法: 返回一个包含对象所有可枚举属性值的数组。 -
Object.entries()方法: 返回一个包含对象所有可枚举属性的[key, value]键值对数组。
2.3 检查属性是否存在
-
in运算符:检查对象是否包含某个属性。console.log('name' in person); // true console.log('job' in person); // false -
hasOwnProperty方法:检查对象本身是否拥有某个属性,而不是继承自原型链。console.log(person.hasOwnProperty('name')); // true
3. 原型链与继承
JavaScript 中的对象是通过原型链继承来共享行为和属性的。每个对象都有一个 __proto__ 属性,指向它的原型对象。
3.1 原型链
-
每个对象都有一个与之关联的原型对象(Prototype),当你访问一个对象的属性时,JavaScript 引擎会首先查找对象本身是否有该属性。如果没有,它会查找对象的原型,再找原型的原型,直到达到
null(即原型链的顶端)。 -
Object.prototype是所有对象的原型链的顶端。
3.2 继承和原型
-
当你通过构造函数创建对象时,新的对象会继承构造函数的原型。
function Person(name, age) { this.name = name; this.age = age; } Person.prototype.greet = function() { console.log(`Hello, my name is ${this.name}`); }; const john = new Person('John', 30); john.greet(); // 'Hello, my name is John'
3.3 Object.create 创建对象
Object.create(proto) 方法创建一个新对象,并将指定的对象作为新对象的原型。
const personProto = {
greet: function() {
console.log(`Hello, my name is ${this.name}`);
}
};
const john = Object.create(personProto);
john.name = 'John';
john.greet(); // 'Hello, my name is John'
4. JavaScript 对象的特殊类型
4.1 Object 构造函数
Object 是一个内置构造函数,它可以用来创建空对象,或者将其他数据类型转换为对象。
-
创建空对象:
const obj = new Object(); -
转换为对象:
const str = 'hello'; const obj = new Object(str); console.log(obj); // String { 'hello' }
4.2 Symbol 类型的属性
Symbol 是 ES6 引入的一种基本数据类型,通常用于给对象添加唯一的属性键,以避免命名冲突。每个 Symbol 值都是唯一的。
const sym = Symbol('id');
const obj = {
[sym]: 123
};
console.log(obj[sym]); // 123
4.3 getter 和 setter
JavaScript 允许通过 get 和 set 方法在对象上定义计算属性,这些属性不需要明确地存储数据,而是根据其他属性来计算。
const person = {
firstName: 'John',
lastName: 'Doe',
get fullName() {
return this.firstName + ' ' + this.lastName;
},
set fullName(name) {
const [firstName, lastName] = name.split(' ');
this.firstName = firstName;
this.lastName = lastName;
}
};
console.log(person.fullName); // 'John Doe'
person.fullName = 'Jane Smith';
console.log(person.firstName); // 'Jane'
console.log(person.lastName); // 'Smith'
5. 对象与 JSON
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它基于 JavaScript 对象字面量的语法。
-
JSON.stringify():将 JavaScript 对象转换为 JSON 字符串。 -
JSON.parse():将 JSON 字符串解析为 JavaScript 对象。
6. 常见面试题
5.1 面试题:什么是 JavaScript 对象,如何创建一个对象?
-
回答:JavaScript 对象是由一组键值对组成的数据结构。你可以使用对象字面量或者
new Object()来创建一个对象。const obj = { key: 'value' }; // 或者 const obj = new Object(); obj.key = 'value';
5.2 面试题:如何判断一个对象是否具有某个属性?
- 回答:
-
使用
in运算符:'property' in obj; -
使用
hasOwnProperty()方法判断是否为对象本身的属性:obj.hasOwnProperty('property');
-
5.3 面试题:什么是原型链?如何访问一个对象的原型?
-
回答:原型链是 JavaScript 中对象之间继承的机制。当你访问对象的属性时,如果对象本身没有该属性,JavaScript 引擎会查找对象的原型,再查找原型的原型,直到找到属性或到达
null。可以通过__proto__来访问一个对象的原型。const person = { name: 'John' }; console.log(person.__proto__); // Object.prototype
5.4 面试题:如何用 Object.create() 创建一个新对象?
-
回答:
Object.create(proto)用来创建一个新对象,并将指定的对象作为新对象的原型。const animal = { eat() { console.log('Eating'); } }; const dog = Object.create(animal); dog.bark = function() { console.log('Barking'); }; dog.eat(); // Eating dog.bark(); // Barking
5.5 面试题:JavaScript 对象的属性存储在哪里,如何优化性能?
- 回答:JavaScript 对象的属性通常存储在哈希表中。为了优化性能,可以通过避免频繁地向对象添加和删除属性,避免对象的频繁变化,或者使用原型链来复用属性和方法。
5.6 面试题:getter 和 setter 是什么?如何使用它们?
-
回答:
getter和setter是用于定义对象的属性访问器的特殊方法。getter用于访问属性值,setter用于修改属性值。const person = { firstName: 'John', lastName: 'Doe', get fullName() { return this.firstName + ' ' + this.lastName; }, set full