JavaScript对象
对象是JavaScript中的核心概念,是一种复合数据类型,可以存储多个键值对。几乎所有的JavaScript值都是对象,除了基本数据类型(字符串、数字、布尔值、null、undefined、符号、大整数)。
对象的创建
JavaScript提供了多种创建对象的方式。
对象字面量
使用花括号{}创建对象:
const person = {
name: "John",
age: 30,
isActive: true
};
Object构造函数
使用Object构造函数创建对象:
const person = new Object();
person.name = "John";
person.age = 30;
person.isActive = true;
构造函数
使用自定义构造函数创建对象:
function Person(name, age) {
this.name = name;
this.age = age;
this.isActive = true;
}
const person = new Person("John", 30);
Object.create()
使用Object.create()方法创建对象:
const personPrototype = {
greet: function() {
return "Hello, " + this.name + "!";
}
};
const person = Object.create(personPrototype);
person.name = "John";
person.age = 30;
类
ES6引入的类语法:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
this.isActive = true;
}
greet() {
return "Hello, " + this.name + "!";
}
}
const person = new Person("John", 30);
对象的属性
属性是对象的键值对。
属性访问
可以使用点号.或方括号[]访问对象属性:
const person = { name: "John", age: 30 };
console.log(person.name); // John
console.log(person["age"]); // 30
方括号语法的优点:
- 可以使用变量作为属性名
- 可以使用包含特殊字符的属性名
const person = { "first name": "John", age: 30 };
const propName = "age";
console.log(person[propName]); // 30
console.log(person["first name"]); // John
属性赋值
const person = {};
// 点号语法
person.name = "John";
// 方括号语法
person["age"] = 30;
属性删除
使用delete操作符删除对象的属性:
const person = { name: "John", age: 30 };
delete person.age;
console.log(person.age); // undefined
属性存在性检查
使用in操作符或hasOwnProperty()方法检查属性是否存在:
const person = { name: "John", age: 30 };
console.log("name" in person); // true
console.log(person.hasOwnProperty("age")); // true
console.log("gender" in person); // false
属性遍历
使用for...in循环遍历对象的可枚举属性:
const person = { name: "John", age: 30, isActive: true };
for (let prop in person) {
console.log(prop + ": " + person[prop]);
}
使用Object.keys()获取对象的可枚举自有属性名:
const person = { name: "John", age: 30, isActive: true };
const keys = Object.keys(person);
console.log(keys); // ["name", "age", "isActive"]
使用Object.values()获取对象的可枚举自有属性值:
const person = { name: "John", age: 30, isActive: true };
const values = Object.values(person);
console.log(values); // ["John", 30, true]
使用Object.entries()获取对象的可枚举自有属性键值对:
const person = { name: "John", age: 30, isActive: true };
const entries = Object.entries(person);
console.log(entries); // [["name", "John"], ["age", 30], ["isActive", true]]
对象的方法
方法是对象的属性,其值是函数。
方法定义
const person = {
name: "John",
age: 30,
greet: function() {
return "Hello, " + this.name + "!";
}
};
// ES6简写语法
const person = {
name: "John",
age: 30,
greet() {
return "Hello, " + this.name + "!";
}
};
方法调用
const person = {
name: "John",
greet() {
return "Hello, " + this.name + "!";
}
};
console.log(person.greet()); // Hello, John!
this关键字
在对象方法中,this指向调用该方法的对象:
const person1 = {
name: "John",
greet() {
return "Hello, " + this.name + "!";
}
};
const person2 = {
name: "Jane",
greet() {
return "Hello, " + this.name + "!";
}
};
console.log(person1.greet()); // Hello, John!
console.log(person2.greet()); // Hello, Jane!
对象的原型
每个JavaScript对象都有一个原型对象,对象可以从原型继承属性和方法。
__proto__属性
使用__proto__属性访问对象的原型:
const person = { name: "John" };
console.log(person.__proto__); // Object.prototype
Object.getPrototypeOf()
使用Object.getPrototypeOf()方法获取对象的原型:
const person = { name: "John" };
const proto = Object.getPrototypeOf(person);
console.log(proto); // Object.prototype
Object.setPrototypeOf()
使用Object.setPrototypeOf()方法设置对象的原型:
const personPrototype = { greet: function() { return "Hello!"; } };
const person = { name: "John" };
Object.setPrototypeOf(person, personPrototype);
console.log(person.greet()); // Hello!
对象的属性描述符
对象的每个属性都有一个属性描述符,用于描述属性的特性。
获取属性描述符
使用Object.getOwnPropertyDescriptor()方法获取属性描述符:
const person = { name: "John" };
const descriptor = Object.getOwnPropertyDescriptor(person, "name");
console.log(descriptor);
// {
// value: "John",
// writable: true,
// enumerable: true,
// configurable: true
// }
属性描述符的特性
- value:属性的值
- writable:是否可以修改属性的值
- enumerable:是否可以枚举(for…in循环和Object.keys()是否包含该属性)
- configurable:是否可以删除属性或修改属性描述符
设置属性描述符
使用Object.defineProperty()方法设置属性描述符:
const person = {};
Object.defineProperty(person, "name", {
value: "John",
writable: false, // 不可修改
enumerable: true,
configurable: true
});
person.name = "Jane"; // 不会生效
console.log(person.name); // John
对象的方法
JavaScript提供了许多内置的对象方法。
Object.assign()
将一个或多个源对象的属性复制到目标对象:
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
const result = Object.assign(target, source1, source2);
console.log(result); // { a: 1, b: 2, c: 3 }
Object.freeze()
冻结对象,使其属性不能被修改、添加或删除:
const person = { name: "John", age: 30 };
Object.freeze(person);
person.name = "Jane"; // 不会生效
delete person.age; // 不会生效
person.gender = "male"; // 不会生效
console.log(person); // { name: "John", age: 30 }
Object.seal()
密封对象,使其属性不能被添加或删除,但可以修改现有属性:
const person = { name: "John", age: 30 };
Object.seal(person);
person.name = "Jane"; // 可以修改
delete person.age; // 不会生效
person.gender = "male"; // 不会生效
console.log(person); // { name: "Jane", age: 30 }
Object.is()
比较两个值是否严格相等:
console.log(Object.is(5, 5)); // true
console.log(Object.is(5, "5")); // false
console.log(Object.is(NaN, NaN)); // true
console.log(Object.is(+0, -0)); // false
对象的继承
JavaScript使用原型链实现继承。
原型继承
const personPrototype = {
greet() {
return "Hello, " + this.name + "!";
}
};
const employeePrototype = Object.create(personPrototype);
employeePrototype.work = function() {
return this.name + " is working.";
};
const employee = Object.create(employeePrototype);
employee.name = "John";
employee.position = "Developer";
console.log(employee.greet()); // Hello, John!
console.log(employee.work()); // John is working.
构造函数继承
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
return "Hello, " + this.name + "!";
};
function Employee(name, position) {
Person.call(this, name); // 调用父构造函数
this.position = position;
}
// 设置原型链
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
Employee.prototype.work = function() {
return this.name + " is working as " + this.position + ".";
};
const employee = new Employee("John", "Developer");
console.log(employee.greet()); // Hello, John!
console.log(employee.work()); // John is working as Developer.
ES6类继承
使用class和extends关键字实现继承:
class Person {
constructor(name) {
this.name = name;
}
greet() {
return "Hello, " + this.name + "!";
}
}
class Employee extends Person {
constructor(name, position) {
super(name); // 调用父类构造函数
this.position = position;
}
work() {
return this.name + " is working as " + this.position + ".";
}
}
const employee = new Employee("John", "Developer");
console.log(employee.greet()); // Hello, John!
console.log(employee.work()); // John is working as Developer.
对象的最佳实践
- 使用对象字面量:优先使用对象字面量创建对象
- 使用const:使用
const声明对象,避免重新赋值 - 使用简洁的方法语法:ES6的简洁方法语法使代码更清晰
- 避免使用
__proto__:使用Object.getPrototypeOf()和Object.setPrototypeOf()代替 - 使用ES6类:对于复杂的对象关系,使用ES6类语法
- 注意this的指向:了解
this在不同上下文中的指向
继续学习:JavaScript数组