1.JavaScript 对象

23 阅读5分钟

Objects

JavaScript对象是属性及其值的集合,可以是任何数据类型,包括其他对象。对象与现实世界的对象相似,因为它们具有描述其特征的属性和定义其行为的方法。

属性定义为键值对。键是表示属性名称的字符串(或标识符),值是属性的实际值。可以通过多种方式创建对象,例如:

  1. 使用对象字面量(object literal)

    let person = {
    	firstName: "John",
    	lastName: "Doe",
    	age: 30,
    	fullName: function() {
    		return this.firstName + " " + this.lastName;
    	}
    };
    
  2. 使用对象构造函数

    let person = new Object();
    person.firstName = "John";
    person.lastName = "Doe";
    person.age = 30;
    
  3. 使用 object.create()方法:

    let person = Object.create(null);
    person.firstName = "John";
    person.lastName = "Doe";
    person.age = 30;
    

对象也可以用作其他对象的原型,这允许继承和重用属性和方法。

JavaScript对象是动态的,这意味着属性和方法可以在运行时添加、删除或修改。对象也通过引用传递,这意味着当一个对象被分配给一个变量时,变量和它引用的对象都引用内存中的同一个底层对象。

对象引用(Object References)

在JavaScript中,对象是通过引用传递的。这意味着当您将对象分配给变量时,该变量在内存中保存对该对象的引用,而不是对象值的副本。

这里有一个例子来说明这个概念:

let person = {name: "John", age: 30};
let anotherPerson = person;

console.log(anotherPerson.name); // Output: "John"

person.name = "Jane";
console.log(anotherPerson.name); // Output: "Jane"

在这个例子中,person对象被分配给anotherPerson变量。由于对象是通过引用传递的,所以两个变量都引用内存中的同一个对象。因此,当person对象的name属性发生变化时,anotherPerson中相同属性的值也会发生变化。

当您想在多个变量之间共享对象的数据时,这种行为会很有帮助,但如果您需要意识到这一点,它也会导致意想不到的结果。如果您想创建对象的副本,您可以使用Object.assign()或扩展运算符…等方法在内存中创建具有相同属性但引用不同的新对象。

let person = {name: "John", age: 30};
let anotherPerson = Object.assign({}, person); // or let anotherPerson = {...person}

person.name = "Jane";
console.log(anotherPerson.name); // Output: "John"

值得注意的是,当涉及到嵌套对象时,引用行为适用于所有嵌套对象,这意味着对嵌套对象的任何更改都将反映在引用它的所有变量中。

访问对象属性

有几种方法可以在JavaScript中访问对象属性:

  1. 使用点表示法:

    let person = {name: "John", age: 30};
    console.log(person.name); // Output: "John"
    console.log(person.age); // Output: 30
    
  2. 使用括号表示法:
    当属性名称存储在变量中或属性名称包含对点表示法无效的特殊字符或空格时,括号表示法很有用。

    let person = {name: "John", age: 30};
    console.log(person["name"]); // Output: "John"
    console.log(person["age"]); // Output: 30
    
  3. 使用Object. getOwnProperty()方法

    let person = {name: "John", age: 30};
    console.log(Object.getOwnPropertyDescriptor(person, "name"));
    

    此方法返回一个描述属性及其属性的对象。此方法返回一个描述属性及其属性的对象。

  4. 使用Object. getOwnPropertyNames()方法

    let person = {name: "John", age: 30};
    console.log(Object.getOwnPropertyNames(person));
    

    此方法返回一个包含对象所有属性的数组。

  5. 使用Object. keys()方法

    let person = {name: "John", age: 30};
    console.log(Object.keys(person));
    

    此方法返回一个包含对象所有可枚举属性的数组。

    需要注意的是,如果您尝试访问对象上不存在的属性,它将返回undefined。

    let person = {name: "John", age: 30};
    console.log(person.height); // Output: undefined
    

    此外,您可以使用in运算符检查对象是否具有特定属性,并使用hasOwnProperty()方法检查对象是否具有未从其原型继承的特定属性。

对象突变-添加、更新和删除属性

在JavaScript中,您可以通过多种方式添加、更新和删除对象属性:

  1. 添加属性

    let person = {name: "John", age: 30};
    person.height = 180; // add new property
    console.log(person); // Output: {name: "John", age: 30, height: 180}
    
  2. 更新属性

    let person = {name: "John", age: 30};
    person.name = "Jane"; // update property
    console.log(person); // Output: {name: "Jane", age: 30}
    
  3. 删除属性

    let person = {name: "John", age: 30};
    delete person.age; // delete property
    console.log(person); // Output: {name: "John"}
    

值得注意的是,delete运算符仅适用于对象的直接属性,而不适用于从其原型继承的属性。

除了这些方法之外,您还可以使用Object.defineProperty()方法来定义新属性或修改现有属性的属性,例如可写、可枚举和可配置。

let person = {name: "John", age: 30};
Object.defineProperty(person, "name", {writable: false});

在此示例中,name属性的writable属性设置为false,以便它将是只读的。

此外,您可以使用Object.defineProperties()方法一次定义多个属性

let person = {name: "John", age: 30};
Object.defineProperties(person, {
	name: {writable: false},
	age: {value: 20}
});

在此示例中,name属性的writable属性设置为false,age属性的值设置为20。

冻结对象

在JavaScript中,冻结对象是属性和值无法修改或删除的对象,Object.freeze()​方法可以创建冻结对象,一旦对象被冻结,其属性和值就无法更改或删除。

这是一个例子:

let person = {name: "John", age: 30};
Object.freeze(person);
person.name = "Jane"; // this will have no effect
console.log(person); // Output: {name: "John", age: 30}

您可以使用Object.isFrozen()​方法来检查对象是否被冻结。

let person = {name: "John", age: 30};
console.log(Object.isFrozen(person)); // Output: false
Object.freeze(person);
console.log(Object.isFrozen(person)); // Output: true

值得注意的是,Object.freeze()​方法只防止修改对象本身的属性和值,而不是其属性的值。如果对象包含任何对象作为属性,这些对象仍然可以修改。

let person = { name: "John", details: { address: "xyz", phone: 123 }};
Object.freeze(person);
console.log(Object.isFrozen(person.details)); // Output: false

为了防止修改冻结对象中的嵌套对象,您可以递归地使用Object.freeze()​。

let person = { name: "John", details: { address: "xyz", phone: 123 }};

function deepFreeze(obj) {
if (typeof obj === 'object' && obj !== null) {
Object.values(obj).forEach(deepFreeze);
Object.freeze(obj);
}
}
deepFreeze(person);
console.log(Object.isFrozen(person.details)); // Output: true

当您想要确保对象的属性和值保持不变并且不能被意外或恶意修改时,冻结对象很有帮助。

值得注意的是,虽然Object.freeze()​防止修改对象的属性,但它仍然允许将对象分配给新的变量或属性,因此仍然可以访问和使用该对象。