深入学习 js Object API

207 阅读21分钟

有一次面试官问小哆啦关于js对象中的一些api顺便重新总结一下巩固一下知识。

参考资料:

ECMAScript® 2024 语言规范 (tc39.es)

Object - JavaScript | MDN (mozilla.org)

思维导图

image.png

大纲

方法返回类型ECMAScript 版本描述
Object.assign()对象ES6将一个或多个源对象的所有可枚举属性的值复制到目标对象中。
Object.create()对象ES5创建一个新对象,该对象的原型为指定的原型对象,并可以包含指定的属性。
Object.defineProperties()对象ES5直接在对象上定义新属性或修改现有属性,返回修改后的对象。
Object.defineProperty()对象ES5直接在对象上定义新属性或修改现有属性,返回修改后的对象。
Object.freeze()对象ES5冻结一个对象,阻止添加新属性,以及阻止修改或删除现有属性。
Object.fromEntries()对象ES10将键值对列表转换为对象。
Object.getOwnPropertyDescriptor()对象ES5获取指定对象上属性的属性描述符。
Object.getOwnPropertyDescriptors()对象ES2017获取对象所有自身属性的属性描述符。
Object.getOwnPropertyNames()数组ES5返回一个数组,包含对象自身所有可枚举和不可枚举属性的名称。
Object.getOwnPropertySymbols()数组ES6返回一个数组,包含对象自身所有 Symbol 类型的属性的 Symbol 值。
Object.getPrototypeOf()对象ES5返回指定对象的原型。
Object.hasOwnProperty()布尔值ES3检查指定属性是否是对象自身的可枚举属性。
Object.isPrototypeOf()布尔值ES5检查一个对象是否是另一个对象的原型。
Object.propertyIsEnumerable()布尔值ES5检查指定属性是否是对象自身的可枚举属性。
Object.valueOf()原始值ES1返回对象的原始值。
Object.toString()字符串ES1返回对象的字符串表示形式。
Object.is()布尔值ES6判断两个值是否是相同的值(与 === 类似),包括处理 NaN-0 的特殊情况。
Object.isExtensible()布尔值ES5判断对象是否可扩展,即是否可以添加新属性。
Object.isSealed()布尔值ES5判断对象是否被密封,即是否不可添加新属性、删除属性,但仍可修改属性值。
Object.keys()数组ES5返回一个数组,包含对象自身所有可枚举属性的名称。
Object.preventExtensions()对象ES5阻止对象扩展,即禁止添加新属性。
Object.seal()对象ES5密封对象,防止添加新属性和删除现有属性,但可以修改属性值。
Object.setPrototypeOf()对象ES6设置对象的原型。
Object.values()数组ES2017返回一个数组,包含对象自身所有可枚举属性的值。

1、构造对象的属性

1.1Object.assign()

用法

Object.assign() 是一个用于将一个或多个源对象的可枚举属性复制到目标对象的方法。语法如下:

Object.assign(target, source1, source2, ...);
  • target: 目标对象,接收属性的对象。
  • source1, source2, ...: 源对象,从这些对象中复制属性到目标对象。

使用场景

  • 对象合并: 用于将多个对象合并到一个目标对象中。
  • 对象克隆: 可以使用 Object.assign({}, source) 来克隆对象。
  • 默认值设置: 可以用于为对象设置默认值。

示例

对象合并

const target = { a: 1, b: 2 };
const source = { b: 3, c: 4 };
const result = Object.assign(target, source);

console.log(result);  // { a: 1, b: 3, c: 4 }

对象克隆

const original = { x: 1, y: 2 };
const clone = Object.assign({}, original);

console.log(clone);  // { x: 1, y: 2 }

默认值设置

const defaults = { a: 1, b: 2, c: 3 };
const userSettings = { b: 5 };
const result = Object.assign({}, defaults, userSettings);

console.log(result);  // { a: 1, b: 5, c: 3 }

在这个例子中,result 包含了 defaultsuserSettings 的合并结果,如果属性在 userSettings 中存在,则会覆盖 defaults 中的相同属性。

注意

  1. 可枚举属性: Object.assign() 只会复制源对象中的可枚举属性。不可枚举属性、Symbols 以及继承属性将被忽略。

    const obj = Object.create({ a: 1 });
    obj.b = 2;
    Object.defineProperty(obj, 'c', {
        value: 3,
        enumerable: false
    });
    
    const result = Object.assign({}, obj);
    console.log(result);  // { b: 2 }
    
  2. 目标对象改变: Object.assign() 是在目标对象上进行操作的,会改变目标对象的值。如果不希望改变原对象,可以传递一个空对象作为目标。

    const target = { a: 1 };
    const source = { b: 2 };
    
    // 修改了目标对象
    const result = Object.assign(target, source);
    console.log(target);  // { a: 1, b: 2 }
    
  3. 浅拷贝: Object.assign() 进行的是浅拷贝,如果源对象的属性值是对象引用,目标对象得到的是该引用。

    const obj1 = { a: { b: 1 } };
    const obj2 = Object.assign({}, obj1);
    
    obj1.a.b = 2;
    console.log(obj2.a.b);  // 2
    
  4. 不处理继承属性和不可枚举属性: Object.assign() 不会复制继承属性和不可枚举属性。

    const parent = { a: 1 };
    const child = Object.create(parent);
    child.b = 2;
    
    const result = Object.assign({}, child);
    console.log(result);  // { b: 2 }
    
  5. Symbol 属性: Object.assign() 可以复制 Symbol 类型的属性。

    const symbolKey = Symbol('key');
    const obj = { [symbolKey]: 'value' };
    
    const result = Object.assign({}, obj);
    console.log(result);  // { [Symbol(key)]: 'value' }
    

总体而言,使用 Object.assign() 时需要注意其对属性的复制规则,了解它是浅拷贝、只复制可枚举属性等特性,以及在某些场景下可能带来的副作用。如果需要深拷贝或处理更复杂的对象结构,可能需要使用其他工具库或实现自定义的深拷贝逻辑。

1.2 Object.create()

用法

Object.create() 是一个用于创建一个新对象,新对象的原型是指定的对象。语法如下:

Object.create(proto, [propertiesObject]);
  • proto: 新对象的原型。可以为 null 或一个对象。
  • propertiesObject (可选): 包含属性描述符的对象。属性描述符可以是数据属性或访问器属性。

使用场景

  • 创建对象: 用于创建一个新对象,继承自指定的原型对象。
  • 原型链继承: 可以通过原型链继承的方式创建对象,实现对象之间的继承关系。

示例

创建对象

const personProto = {
    greet: function() {
        console.log(`Hello, ${this.name}!`);
    }
};

const john = Object.create(personProto);
john.name = 'John Doe';

john.greet();  // Hello, John Doe!

原型链继承

const animal = {
    makeSound: function() {
        console.log('Some generic sound');
    }
};

const dog = Object.create(animal);
dog.makeSound();  // Some generic sound

// Adding specific behavior for dog
dog.bark = function() {
    console.log('Woof! Woof!');
};

dog.bark();  // Woof! Woof!

注意

  1. 参数为 null 如果 Object.create() 的第一个参数为 null,则创建的对象没有原型,它不继承任何属性或方法。

    const obj = Object.create(null);
    console.log(obj.toString);  // undefined
    
  2. 原型链继承: 通过 Object.create() 创建的对象可以通过原型链继承属性和方法,可以实现简单的继承关系。

    const parent = {
        sayHello: function() {
            console.log('Hello!');
        }
    };
    
    const child = Object.create(parent);
    child.sayHello();  // Hello!
    
  3. 属性描述符: 可以通过第二个参数 propertiesObject 来定义新对象的属性。这个参数是一个包含属性描述符的对象,可以设置属性的值、可写性、可枚举性等。

    const obj = Object.create(null, {
        name: {
            value: 'John',
            writable: true,
            enumerable: true
        }
    });
    
    console.log(obj.name);  // John
    

Object.create() 是一种强大的对象创建方式,特别适用于实现原型链继承和创建具有特定原型的新对象。在使用时需要注意参数的合法性和原型链的继承关系。

1.3 Object.defineProperties()

用法

Object.defineProperties() 方法用于定义或修改对象的多个属性。语法如下:

Object.defineProperties(obj, props);
  • obj: 要定义或修改属性的对象。
  • props: 包含一个或多个属性描述符的对象。每个属性描述符都是一个键值对,键是属性名称,值是属性描述符对象。

使用场景

  • 批量定义属性: 用于一次性定义或修改多个对象的属性。
  • 控制属性特性: 可以通过属性描述符详细控制属性的特性,如可写性、可枚举性、可配置性等。

示例

const person = {};

Object.defineProperties(person, {
    name: {
        value: 'John',
        writable: true,
        enumerable: true
    },
    age: {
        value: 30,
        writable: true,
        enumerable: true
    },
    sayHello: {
        value: function() {
            console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
        },
        enumerable: false
    }
});

console.log(person.name);      // John
console.log(person.age);       // 30
person.sayHello();             // Hello, my name is John and I'm 30 years old.

// Properties won't be displayed in for...in loop due to enumerable: false
for (const key in person) {
    console.log(key);  // name, age
}

注意

  1. 属性描述符: props 中的每个属性描述符都是一个对象,包含键值对,定义了属性的各种特性。常见的属性描述符属性有 valuewritableenumerableconfigurable 等。

  2. 可配置性: 通过 Object.defineProperties() 定义的属性,默认是可配置的。如果需要改变某个属性的配置,可以通过后续调用 Object.defineProperty() 来实现。

  3. 可枚举性: 默认情况下,通过 Object.defineProperties() 定义的属性是可枚举的。可以通过设置 enumerablefalse 来使属性不可枚举,这样它就不会出现在 for...in 循环中。

  4. 不可变性: Object.defineProperties() 一般用于一次性定义对象的多个属性,它并不会添加新的属性。如果需要添加或修改单个属性,可以使用 Object.defineProperty()

Object.defineProperty(obj, 'newProperty', {
    value: 'new value',
    writable: true,
    enumerable: true,
    configurable: true
});

总体而言,Object.defineProperties() 提供了一种方便的方式,可以一次性定义或修改多个对象的属性,并通过属性描述符详细控制这些属性的特性。

1.4 Object.defineProperty()

用法

Object.defineProperty() 方法用于在对象上定义一个新属性或修改现有属性,并返回修改后的对象。语法如下:

Object.defineProperty(obj, prop, descriptor);
  • obj: 要在其上定义属性的对象。
  • prop: 要定义或修改的属性的名称。
  • descriptor: 属性描述符对象,包含属性的各种特性。

使用场景

  • 定义新属性: 可以用于向对象添加新属性。
  • 修改属性特性: 可以用于修改现有属性的特性,如可写性、可枚举性、可配置性等。

示例

const person = {};

Object.defineProperty(person, 'name', {
    value: 'John',
    writable: true,
    enumerable: true
});

console.log(person.name);  // John

// Modifying property attributes
Object.defineProperty(person, 'age', {
    value: 30,
    writable: false,      // Can't be changed
    enumerable: true
});

console.log(person.age);  // 30
// This will cause an error because 'age' is not writable
person.age = 31;

// Adding a getter function
Object.defineProperty(person, 'fullName', {
    get: function() {
        return `${this.name} Doe`;
    },
    enumerable: true
});

console.log(person.fullName);  // John Doe

注意

  1. 属性描述符: descriptor 是一个对象,包含键值对,定义了属性的各种特性。常见的属性描述符属性有 valuewritableenumerableconfigurablegetset 等。

  2. 可写性: 如果设置 writablefalse,则属性值是不可写的,无法通过赋值修改。默认值为 false

  3. 可配置性: 如果设置 configurablefalse,则无法再使用 Object.defineProperty() 修改该属性的特性,也无法使用 delete 删除该属性。默认值为 false

  4. 可枚举性: 默认情况下,通过 Object.defineProperty() 定义的属性是可枚举的。可以通过设置 enumerablefalse 来使属性不可枚举。

  5. 存取器属性: 可以通过设置 getset 来定义存取器属性,这样属性值不是直接存储在对象中,而是通过 getter 和 setter 方法进行获取和设置。

const person = {
    _age: 30,
    get age() {
        return this._age;
    },
    set age(value) {
        if (value >= 0) {
            this._age = value;
        } else {
            console.error('Age must be a non-negative value.');
        }
    }
};

console.log(person.age);  // 30
person.age = 31;
console.log(person.age);  // 31
person.age = -1;  // Error: Age must be a non-negative value.

总体而言,Object.defineProperty() 提供了一种灵活的方式,可以定义或修改对象的属性,并通过属性描述符详细控制这些属性的特性。

1.5 Object.freeze()

Object.freeze() 是一个 JavaScript 方法,用于冻结对象,使其属性不可更改。一旦冻结对象,就无法添加、删除或修改其属性。这包括对属性值的更改以及对属性特性(如可写性)的更改。

用法

Object.freeze() 用于冻结对象,使其属性不可修改。语法如下:

Object.freeze(obj);
  • obj: 要冻结的对象。

示例

const person = {
    name: 'John',
    age: 30
};

Object.freeze(person);

// Attempting to modify the frozen object will result in an error
person.age = 31;  // Error: Cannot assign to read only property 'age' of object

注意

  1. 冻结后的对象属性不可修改,包括添加、删除、修改属性值等操作。
  2. Object.freeze() 是浅冻结,即它只会冻结对象的第一层属性,而不会递归冻结嵌套对象。
  3. 冻结后的对象是不可扩展的,即无法添加新属性。

用途和注意事项

  • 防止意外修改: 当你希望确保对象的属性不被意外修改时,可以使用 Object.freeze()。这在维护不可变性或防止意外更改时很有用。

    const config = {
        API_KEY: '12345',
        MAX_REQUESTS: 100
    };
    
    Object.freeze(config);
    
    // Attempting to modify a frozen object will result in an error
    config.MAX_REQUESTS = 200;  // Error: Cannot assign to read only property 'MAX_REQUESTS' of object
    
  • 保护常量对象: 当你定义一组常量,并希望确保它们不会被修改时,可以使用 Object.freeze()

    const constants = {
        PI: 3.14159,
        GRAVITY: 9.8
    };
    
    Object.freeze(constants);
    
    // Attempting to modify a frozen object will result in an error
    constants.PI = 3;  // Error: Cannot assign to read only property 'PI' of object
    
  • 注意浅冻结: 如果对象具有嵌套结构,Object.freeze() 只会冻结顶层属性,而不会递归冻结嵌套对象。

    const nestedObject = {
        outer: {
            inner: 42
        }
    };
    
    Object.freeze(nestedObject);
    
    // Attempting to modify the inner property will NOT result in an error
    nestedObject.outer.inner = 99;
    console.log(nestedObject.outer.inner);  // 99
    

总体而言,Object.freeze() 是一种用于确保对象不可更改的强大方法,适用于一些需要保护数据完整性的场景。

1.6 Object.fromEntries()

Object.fromEntries() 是一个 JavaScript 方法,用于将键值对的数组转换为对象。它接收一个包含键值对的数组,返回一个新的对象,其中数组中的每个元素都是一个二元数组,第一个元素为键,第二个元素为对应的值。该方法在 ECMAScript 2019 标准中被引入。

用法

Object.fromEntries() 用于将键值对的数组转换为对象。语法如下:

Object.fromEntries(iterable);
  • iterable: 一个可迭代对象,通常是包含键值对的数组。

示例

const entries = [
    ['name', 'John'],
    ['age', 30],
    ['city', 'New York']
];

const person = Object.fromEntries(entries);
console.log(person);
// Output: { name: 'John', age: 30, city: 'New York' }

注意

  1. iterable 必须是一个可迭代对象,通常是一个包含键值对的数组。
  2. Object.fromEntries() 可以用于将 Object.entries() 方法生成的数组重新转回为对象。

用途

  • 数组转为对象: 当你有一个包含键值对的数组时,可以使用 Object.fromEntries() 来创建一个新的对象。

    const entries = [
        ['name', 'John'],
        ['age', 30],
        ['city', 'New York']
    ];
    
    const person = Object.fromEntries(entries);
    console.log(person);
    // Output: { name: 'John', age: 30, city: 'New York' }
    
  • Object.entries() 配合使用: 可以与 Object.entries() 一起使用,将对象转为包含键值对的数组,然后再用 Object.fromEntries() 转回为对象。

    const person = {
        name: 'John',
        age: 30,
        city: 'New York'
    };
    
    const entries = Object.entries(person);
    console.log(entries);
    // Output: [ ['name', 'John'], ['age', 30], ['city', 'New York'] ]
    
    const reconstructedPerson = Object.fromEntries(entries);
    console.log(reconstructedPerson);
    // Output: { name: 'John', age: 30, city: 'New York' }
    

总体而言,Object.fromEntries() 提供了一种简洁的方式,用于从包含键值对的数组创建对象,特别是在与 Object.entries() 一起使用时,使对象的转换更为方便。

1.7Object.getOwnPropertyDescriptor()

Object.getOwnPropertyDescriptor() 是一个 JavaScript 方法,用于获取对象属性的属性描述符。属性描述符是一个对象,包含有关属性(如值、可写性、可配置性等)的信息。

用法

Object.getOwnPropertyDescriptor() 用于获取对象属性的属性描述符。语法如下:

Object.getOwnPropertyDescriptor(obj, prop);
  • obj: 要获取属性描述符的对象。
  • prop: 要获取属性描述符的属性名称。

示例

const person = {
    name: 'John',
    age: 30
};

const descriptor = Object.getOwnPropertyDescriptor(person, 'name');
console.log(descriptor);
/*
Output:
{
    value: 'John',
    writable: true,
    enumerable: true,
    configurable: true
}
*/

注意

  1. 如果属性不存在,Object.getOwnPropertyDescriptor() 将返回 undefined

属性描述符对象

Object.getOwnPropertyDescriptor() 返回一个属性描述符对象,其中包含以下属性:

  • value: 属性的值。
  • writable: 属性是否可写。如果为 true,则属性可写;如果为 false,则属性不可写。
  • enumerable: 属性是否可枚举。如果为 true,则属性可枚举;如果为 false,则属性不可枚举。
  • configurable: 属性是否可配置。如果为 true,则属性可配置;如果为 false,则属性不可配置。

用途

  • 了解属性特性: 当你需要了解对象的某个属性的特性时,可以使用 Object.getOwnPropertyDescriptor()

    const person = {
        name: 'John',
        age: 30
    };
    
    const descriptor = Object.getOwnPropertyDescriptor(person, 'name');
    console.log(descriptor);
    /*
    Output:
    {
        value: 'John',
        writable: true,
        enumerable: true,
        configurable: true
    }
    */
    
  • 验证属性的存在性: 可以通过检查返回值是否为 undefined 来验证对象是否具有特定的属性。

    const person = {
        name: 'John',
        age: 30
    };
    
    const nameDescriptor = Object.getOwnPropertyDescriptor(person, 'name');
    if (nameDescriptor !== undefined) {
        console.log('The property "name" exists in the object.');
    } else {
        console.log('The property "name" does not exist in the object.');
    }
    

总体而言,Object.getOwnPropertyDescriptor() 是一个用于获取对象属性的属性描述符的实用方法,特别是当你需要了解或验证对象属性的特性时。

1.8 Object.getOwnPropertyDescriptors()

Object.getOwnPropertyDescriptors() 是一个 JavaScript 方法,用于获取对象的所有自身属性的属性描述符。它返回一个对象,其中属性名是对象的属性名称,属性值是相应属性的属性描述符对象。这个方法在 ECMAScript 2017(ES8)中被引入。

用法

Object.getOwnPropertyDescriptors() 用于获取对象的所有自身属性的属性描述符。语法如下:

Object.getOwnPropertyDescriptors(obj);
  • obj: 要获取属性描述符的对象。

示例

const person = {
    name: 'John',
    age: 30
};

const descriptors = Object.getOwnPropertyDescriptors(person);
console.log(descriptors);
/*
Output:
{
    name: {
        value: 'John',
        writable: true,
        enumerable: true,
        configurable: true
    },
    age: {
        value: 30,
        writable: true,
        enumerable: true,
        configurable: true
    }
}
*/

注意

  1. Object.getOwnPropertyDescriptors() 返回一个对象,其中属性名是对象的属性名称,属性值是相应属性的属性描述符对象。
  2. Object.getOwnPropertyDescriptor() 不同,Object.getOwnPropertyDescriptors() 返回所有自身属性的属性描述符,而不仅仅是单个属性。

用途

  • 属性复制/克隆: 可以使用 Object.getOwnPropertyDescriptors() 来获取源对象的所有属性描述符,然后使用 Object.defineProperties()Object.create() 等方法将这些属性描述符应用到目标对象,实现属性的复制或克隆。

    const source = {
        name: 'John',
        age: 30
    };
    
    const target = {};
    const descriptors = Object.getOwnPropertyDescriptors(source);
    
    Object.defineProperties(target, descriptors);
    
    console.log(target);
    /*
    Output:
    {
        name: 'John',
        age: 30
    }
    */
    
  • 保留属性特性: 在一些需要复制对象属性并保留其特性的情况下,Object.getOwnPropertyDescriptors() 是一个非常有用的方法。

    const source = {
        name: 'John',
        age: 30
    };
    
    const target = {};
    const descriptors = Object.getOwnPropertyDescriptors(source);
    
    // 修改目标对象的属性,不影响源对象
    target.name = 'Alice';
    
    console.log(source.name);  // John
    console.log(target.name);  // Alice
    

总体而言,Object.getOwnPropertyDescriptors() 提供了一种方便的方法,用于获取对象的所有自身属性的属性描述符,特别适用于属性复制、克隆或在对象之间保留属性特性的场景。

1.9 Object.getOwnPropertyNames()

Object.getOwnPropertyNames() 是一个 JavaScript 方法,用于获取对象的所有自身属性的属性名(包括不可枚举属性)。这个方法返回一个数组,其中包含了对象的所有自身属性的名称

用法

Object.getOwnPropertyNames() 用于获取对象的所有自身属性的属性名。语法如下:

Object.getOwnPropertyNames(obj);
  • obj: 要获取属性名的对象。

示例

const person = {
    name: 'John',
    age: 30
};

const propertyNames = Object.getOwnPropertyNames(person);
console.log(propertyNames);
// Output: ['name', 'age']

注意

  1. Object.getOwnPropertyNames() 返回一个数组,其中包含了对象的所有自身属性的名称,包括不可枚举属性。
  2. Object.keys() 不同,Object.getOwnPropertyNames() 返回的数组包括对象的所有属性,不论属性是否可枚举。

用途

  • 获取对象的所有属性名: 当你需要获取对象的所有属性名,包括不可枚举属性时,可以使用 Object.getOwnPropertyNames()

    const person = {
        name: 'John',
        age: 30
    };
    
    const propertyNames = Object.getOwnPropertyNames(person);
    console.log(propertyNames);
    // Output: ['name', 'age']
    
  • 遍历对象的所有属性: 可以使用 Object.getOwnPropertyNames() 遍历对象的所有属性,包括不可枚举属性。

    const person = {
        name: 'John',
        age: 30
    };
    
    Object.getOwnPropertyNames(person).forEach(propertyName => {
        const propertyValue = person[propertyName];
        console.log(`${propertyName}: ${propertyValue}`);
    });
    /*
    Output:
    name: John
    age: 30
    */
    
  • 获取对象的可枚举属性: 如果只需要获取对象的可枚举属性名,可以使用 Object.keys()

    const person = {
        name: 'John',
        age: 30
    };
    
    const enumerablePropertyNames = Object.keys(person);
    console.log(enumerablePropertyNames);
    // Output: ['name', 'age']
    

总体而言,Object.getOwnPropertyNames() 是一个获取对象自身属性名的有用方法,特别是当需要包括不可枚举属性时。

1.10 Object.getOwnPropertySymbols()

Object.getOwnPropertySymbols() 是一个 JavaScript 方法,用于获取对象的所有自身的 Symbol 类型的属性。这个方法返回一个数组,其中包含了对象的所有自身的 Symbol 类型的属性。以下是关于 Object.getOwnPropertySymbols() 的详细说明:

用法

Object.getOwnPropertySymbols() 用于获取对象的所有自身的 Symbol 类型的属性。语法如下:

Object.getOwnPropertySymbols(obj);
  • obj: 要获取 Symbol 属性的对象。

示例

const person = {
    [Symbol('id')]: '12345',
    name: 'John',
    age: 30
};

const symbols = Object.getOwnPropertySymbols(person);
console.log(symbols);
// Output: [ Symbol(id) ]

注意

  1. Object.getOwnPropertySymbols() 返回一个数组,其中包含了对象的所有自身的 Symbol 类型的属性。
  2. 返回的数组中的 Symbol 属性的顺序取决于它们被添加到对象的顺序。

用途

  • 获取对象的 Symbol 属性: 当你需要获取对象的所有自身的 Symbol 类型的属性时,可以使用 Object.getOwnPropertySymbols()

    const person = {
        [Symbol('id')]: '12345',
        name: 'John',
        age: 30
    };
    
    const symbols = Object.getOwnPropertySymbols(person);
    console.log(symbols);
    // Output: [ Symbol(id) ]
    
  • 遍历对象的 Symbol 属性: 可以使用 Object.getOwnPropertySymbols() 遍历对象的所有 Symbol 类型的属性。

    const person = {
        [Symbol('id')]: '12345',
        name: 'John',
        age: 30
    };
    
    Object.getOwnPropertySymbols(person).forEach(symbol => {
        const propertyValue = person[symbol];
        console.log(`${symbol.toString()}: ${propertyValue}`);
    });
    /*
    Output:
    Symbol(id): 12345
    */
    
  • Symbol 属性的应用: Symbol 类型的属性常用于创建对象的私有属性,因为它们不会被 Object.keys()Object.getOwnPropertyNames() 等方法返回。

    const privateData = Symbol('privateData');
    
    const person = {
        [privateData]: 'Sensitive information',
        name: 'John',
        age: 30
    };
    
    const symbols = Object.getOwnPropertySymbols(person);
    console.log(symbols);  // Output: [ Symbol(privateData) ]
    

总体而言,Object.getOwnPropertySymbols() 提供了一种获取对象的所有自身的 Symbol 类型的属性的方法,常用于处理对象的 Symbol 属性或创建对象的私有属性。

1.11Object.getPrototypeOf()

Object.getPrototypeOf() 是一个 JavaScript 方法,用于获取指定对象的原型(prototype)。这个方法返回对象的原型,即对象继承属性和方法的来源。

用法

Object.getPrototypeOf() 用于获取指定对象的原型。语法如下:

Object.getPrototypeOf(obj);
  • obj: 要获取原型的对象。

示例

function Dog(name) {
    this.name = name;
}

const myDog = new Dog('Buddy');
const prototypeOfMyDog = Object.getPrototypeOf(myDog);

console.log(prototypeOfMyDog === Dog.prototype);  // true

注意

  1. 如果对象没有显式指定原型,Object.getPrototypeOf() 将返回对象的隐式原型(通过构造函数的 prototype 属性定义)。
  2. Object.getPrototypeOf() 是获取原型的标准方法,与 .__proto__ 属性相比,它更推荐使用。

用途

  • 获取对象的原型: 当你需要获取对象的原型时,可以使用 Object.getPrototypeOf()

    function Cat(name) {
        this.name = name;
    }
    
    const myCat = new Cat('Whiskers');
    const prototypeOfMyCat = Object.getPrototypeOf(myCat);
    
    console.log(prototypeOfMyCat === Cat.prototype);  // true
    
  • 验证对象的原型: 可以使用 Object.getPrototypeOf() 来验证对象的原型是否符合预期。

    function Vehicle() {}
    
    function Car() {}
    Car.prototype = Object.create(Vehicle.prototype);
    
    const myCar = new Car();
    const prototypeOfMyCar = Object.getPrototypeOf(myCar);
    
    console.log(prototypeOfMyCar === Car.prototype);    // true
    console.log(prototypeOfMyCar === Vehicle.prototype); // false
    
  • 查找对象的原型链: 通过反复调用 Object.getPrototypeOf() 可以查找对象的完整原型链。

    function Animal() {}
    
    function Mammal() {}
    Mammal.prototype = Object.create(Animal.prototype);
    
    function Dog() {}
    Dog.prototype = Object.create(Mammal.prototype);
    
    const myDog = new Dog();
    const proto1 = Object.getPrototypeOf(myDog);
    const proto2 = Object.getPrototypeOf(proto1);
    
    console.log(proto1 === Dog.prototype);   // true
    console.log(proto2 === Mammal.prototype);  // true
    

总体而言,Object.getPrototypeOf() 是一个用于获取对象原型的常用方法,适用于检查对象的原型和原型链。

1.12 Object.hasOwm()

如果指定的对象自身有指定的属性,则静态方法 Object.hasOwn() 返回 true。如果属性是继承的或者不存在,该方法返回 false

Object.hasOwn() 旨在取代 Object.prototype.hasOwnProperty()

1.13 Object.is()

Object.is() 是 JavaScript 中的一个方法,用于比较两个值是否严格相等。与严格相等运算符 === 类似,但有一些特殊的行为。

用法

Object.is() 用于比较两个值是否严格相等。语法如下:

Object.is(value1, value2);
  • value1value2: 要比较的两个值。

特殊行为

  • 对于正零和负零,Object.is() 认为它们是相等的。

    console.log(Object.is(0, -0));  // false
    console.log(Object.is(+0, -0)); // false
    
    console.log(Object.is(NaN, NaN)); // true
    
  • 对于 NaNObject.is() 认为它与自身相等。

示例

const a = 5;
const b = '5';

// 使用 Object.is() 检查值是否严格相等
if (Object.is(a, b)) {
    console.log('a is strictly equal to b.');
} else {
    console.log('a is not strictly equal to b.');
}

在上述示例中,Object.is() 用于比较变量 a 是否严格等于变量 b。这与 === 运算符相似,但有一些特殊的行为。

Object.is() 在某些情况下比 === 更精确,并且通常用于特殊比较要求,例如处理 NaN 或正负零。在一般情况下,如果不涉及到这些特殊情况,=== 通常是更常用的比较方式。

1.14 Object.isExtensible()

Object.isExtensible() 是 JavaScript 中的一个方法,用于检查对象是否可扩展。可扩展性是指是否可以向对象添加新属性。

用法

Object.isExtensible() 用于检查对象是否可扩展。语法如下:

Object.isExtensible(obj);
  • obj: 要检查是否可扩展的对象。

返回值

如果对象是可扩展的,则 Object.isExtensible() 返回 true,否则返回 false

示例

const myObject = { key: 'value' };

// 检查对象是否可扩展
const isExtensible = Object.isExtensible(myObject);

console.log(isExtensible);  // true

// 阻止对象扩展
Object.preventExtensions(myObject);

// 再次检查对象是否可扩展
const isNowExtensible = Object.isExtensible(myObject);

console.log(isNowExtensible);  // false

在上述示例中,首先使用 Object.isExtensible() 检查对象是否可扩展,然后使用 Object.preventExtensions() 阻止对象扩展,最后再次检查对象是否可扩展。

用途

  • 检查对象是否可扩展: 当你需要确定对象是否可以添加新属性时,可以使用 Object.isExtensible()

    const myObject = { key: 'value' };
    
    if (Object.isExtensible(myObject)) {
        console.log('myObject is extensible. You can add new properties.');
    } else {
        console.log('myObject is not extensible. You cannot add new properties.');
    }
    
  • 防止对象扩展: 可以使用 Object.preventExtensions() 阻止对象扩展,使其变为不可扩展。

    const myObject = { key: 'value' };
    
    Object.preventExtensions(myObject);
    
    if (Object.isExtensible(myObject)) {
        console.log('myObject is extensible.');
    } else {
        console.log('myObject is not extensible.');
    }
    

总体而言,Object.isExtensible() 是一个用于检查对象是否可扩展的方法,通常用于对象属性的管理和控制。

1.15 Object.isFrozen()

Object.isFrozen() 是 JavaScript 中的一个方法,用于检查对象是否被冻结(即不能添加新属性、删除属性或修改属性值)。

用法

Object.isFrozen() 用于检查对象是否被冻结。语法如下:

Object.isFrozen(obj);
  • obj: 要检查是否被冻结的对象。

返回值

如果对象被冻结,则 Object.isFrozen() 返回 true,否则返回 false

示例

const myObject = { key: 'value' };

// 检查对象是否被冻结
const isFrozen = Object.isFrozen(myObject);

console.log(isFrozen);  // false

// 冻结对象
Object.freeze(myObject);

// 再次检查对象是否被冻结
const isNowFrozen = Object.isFrozen(myObject);

console.log(isNowFrozen);  // true

在上述示例中,首先使用 Object.isFrozen() 检查对象是否被冻结,然后使用 Object.freeze() 冻结对象,最后再次检查对象是否被冻结。

用途

  • 检查对象是否被冻结: 当你需要确定对象是否被冻结时,可以使用 Object.isFrozen()

    const myObject = { key: 'value' };
    
    if (Object.isFrozen(myObject)) {
        console.log('myObject is frozen. You cannot modify it.');
    } else {
        console.log('myObject is not frozen. You can modify it.');
    }
    
  • 冻结对象: 可以使用 Object.freeze() 冻结对象,使其成为只读。

    const myObject = { key: 'value' };
    
    Object.freeze(myObject);
    
    if (Object.isFrozen(myObject)) {
        console.log('myObject is frozen. You cannot modify it.');
    } else {
        console.log('myObject is not frozen. You can modify it.');
    }
    

总体而言,Object.isFrozen() 是一个用于检查对象是否被冻结的方法,通常用于确保对象的不可变性。

1.15 Object.isSealed()

Object.isSealed() 是 JavaScript 中的一个方法,用于检查对象是否被密封(即不能添加新属性,不能删除现有属性,但可以修改属性值)。

用法

Object.isSealed() 用于检查对象是否被密封。语法如下:

Object.isSealed(obj);
  • obj: 要检查是否被密封的对象。

返回值

如果对象被密封,则 Object.isSealed() 返回 true,否则返回 false

示例

const myObject = { key: 'value' };

// 检查对象是否被密封
const isSealed = Object.isSealed(myObject);

console.log(isSealed);  // false

// 密封对象
Object.seal(myObject);

// 再次检查对象是否被密封
const isNowSealed = Object.isSealed(myObject);

console.log(isNowSealed);  // true

在上述示例中,首先使用 Object.isSealed() 检查对象是否被密封,然后使用 Object.seal() 密封对象,最后再次检查对象是否被密封。

用途

  • 检查对象是否被密封: 当你需要确定对象是否被密封时,可以使用 Object.isSealed()

    const myObject = { key: 'value' };
    
    if (Object.isSealed(myObject)) {
        console.log('myObject is sealed. You cannot add or remove properties.');
    } else {
        console.log('myObject is not sealed. You can add or remove properties.');
    }
    
  • 密封对象: 可以使用 Object.seal() 密封对象,防止添加或删除属性。

    const myObject = { key: 'value' };
    
    Object.seal(myObject);
    
    if (Object.isSealed(myObject)) {
        console.log('myObject is sealed. You cannot add or remove properties.');
    } else {
        console.log('myObject is not sealed. You can add or remove properties.');
    }
    

总体而言,Object.isSealed() 是一个用于检查对象是否被密封的方法,通常用于确保对象的稳定性和防止属性的动态修改。

对象的密封(Sealing)是一种限制对象结构变动的机制,即对象一旦被密封,就不能再添加新属性、删除现有属性,但仍然可以修改现有属性的值。密封是对象的一种状态。

密封对象并不影响属性值的修改,只是限制了属性的添加和删除。如果需要完全禁止对对象的修改,包括属性值的修改,可以使用 Object.freeze(obj) 方法,这将冻结对象,使其成为不可变对象。

1.16 Object.keys()

在 JavaScript 中,Object.keys() 是一个用于获取对象自身可枚举属性的方法。它返回一个包含对象所有可枚举属性名称的数组。

用法

Object.keys() 的语法如下:

Object.keys(obj);
  • obj: 要获取可枚举属性的对象。

返回值

返回一个包含对象自身可枚举属性名称的数组。

示例

const myObject = {
    name: 'John',
    age: 30,
    city: 'New York'
};

const keys = Object.keys(myObject);

console.log(keys);
// Output: [ 'name', 'age', 'city' ]

在上述示例中,Object.keys() 用于获取 myObject 的可枚举属性名称,然后返回一个包含这些属性名称的数组。

用途

  • 遍历对象的属性名称: 当你需要获取对象的属性名称并进行遍历时,可以使用 Object.keys()

    const myObject = {
        name: 'John',
        age: 30,
        city: 'New York'
    };
    
    const keys = Object.keys(myObject);
    
    keys.forEach(key => {
        const value = myObject[key];
        console.log(`${key}: ${value}`);
    });
    
  • 获取对象的属性数量: 通过获取 Object.keys(obj).length 可以快速获取对象的属性数量。

    const myObject = {
        name: 'John',
        age: 30,
        city: 'New York'
    };
    
    const numberOfProperties = Object.keys(myObject).length;
    
    console.log(`Number of properties: ${numberOfProperties}`);
    

总体而言,Object.keys() 是一个常用的工具方法,用于获取对象的属性名称,特别是在需要遍历对象属性或获取属性数量时。需要注意的是,它只返回对象的自身可枚举属性,不包括原型链上的属性。

1.17Object.preventExtensions()

Object.preventExtensions() 是 JavaScript 中的一个方法,用于阻止对象扩展,即防止向对象添加新的属性。一旦对象被阻止扩展,就不能再向其添加新属性,但可以修改或删除已有属性。

用法

Object.preventExtensions() 用于阻止对象扩展。语法如下:

Object.preventExtensions(obj);
  • obj: 要阻止扩展的对象。

返回值

返回被阻止扩展的对象。

示例

const myObject = { name: 'John', age: 30 };

// 阻止对象扩展
Object.preventExtensions(myObject);

myObject.city = 'New York'; // 无效,不能添加新属性

myObject.age = 31; // 有效,可以修改已有属性的值

delete myObject.name; // 有效,可以删除已有属性

console.log(myObject); // { name: undefined, age: 31 }

在上述示例中,首先使用 Object.preventExtensions() 阻止了 myObject 的扩展,然后尝试向其添加新属性,但这是无效的。但仍然可以修改或删除已有属性。

用途

  • 防止对象扩展: 当你希望确保对象的结构不再发生变化,即不能再添加新属性时,可以使用 Object.preventExtensions()

    const myObject = { name: 'John', age: 30 };
    
    Object.preventExtensions(myObject);
    
    myObject.city = 'New York'; // 无效,不能添加新属性
    
  • 检查对象是否可扩展: 你可以使用 Object.isExtensible(obj) 方法来检查对象是否可扩展。

    const myObject = { name: 'John', age: 30 };
    
    console.log(Object.isExtensible(myObject)); // true
    
    Object.preventExtensions(myObject);
    
    console.log(Object.isExtensible(myObject)); // false
    

总体而言,Object.preventExtensions() 是一个用于阻止对象扩展的方法,通常用于确保对象结构的稳定性,以防止在运行时动态添加新属性。

1.18 Object.seal()

Object.seal() 是 JavaScript 中的一个方法,用于密封对象,使其不能添加新属性、删除现有属性,但可以修改属性值。密封是对象的一种状态,通过 Object.seal() 方法可以将对象设置为密封状态。

用法

Object.seal() 用于密封对象,防止添加新属性和删除现有属性。语法如下:

Object.seal(obj);
  • obj: 要密封的对象。

返回值

返回被密封的对象。

示例

const myObject = { name: 'John', age: 30 };

// 密封对象
Object.seal(myObject);

myObject.city = 'New York'; // 无效,不能添加新属性
delete myObject.name; // 无效,不能删除属性

myObject.age = 31; // 有效,可以修改已有属性的值

console.log(myObject); // { name: 'John', age: 31 }

在上述示例中,首先使用 Object.seal() 密封了 myObject,然后尝试向其添加新属性或删除属性,但这是无效的。但仍然可以修改已有属性的值。

用途

  • 密封对象: 当你希望对象不能再添加新属性、删除属性,但仍然可以修改属性值时,可以使用 Object.seal()

    const myObject = { name: 'John', age: 30 };
    
    Object.seal(myObject);
    
    myObject.city = 'New York'; // 无效,不能添加新属性
    delete myObject.name; // 无效,不能删除属性
    
  • 检查对象是否被密封: 你可以使用 Object.isSealed(obj) 方法来检查对象是否被密封。

    const myObject = { name: 'John', age: 30 };
    
    console.log(Object.isSealed(myObject)); // false
    
    Object.seal(myObject);
    
    console.log(Object.isSealed(myObject)); // true
    

密封对象的主要目的是确保对象的结构不会在运行时被意外地修改,从而提高代码的可靠性和稳定性。密封通常用于那些不希望随意修改结构的对象,例如一些配置对象、常量对象等。

1.19Object.setPrototypeOf()

Object.setPrototypeOf() 是 JavaScript 中的一个方法,用于设置对象的原型。通过这个方法,可以改变对象的原型链。

用法

Object.setPrototypeOf() 用于设置对象的原型。语法如下:

Object.setPrototypeOf(obj, prototype);
  • obj: 要设置原型的对象。
  • prototype: 新的原型对象。

返回值

返回已经设置了新原型的对象。

示例

const myObject = { name: 'John' };
const newPrototype = { age: 30 };

// 设置新的原型
Object.setPrototypeOf(myObject, newPrototype);

console.log(myObject.name); // 'John'
console.log(myObject.age);  // 30

在上述示例中,myObject 的原型被设置为 newPrototype,因此可以访问 age 属性。

用途

  • 改变对象的原型链: 当你希望动态改变对象的原型链时,可以使用 Object.setPrototypeOf()

    const myObject = { name: 'John' };
    const newPrototype = { age: 30 };
    
    Object.setPrototypeOf(myObject, newPrototype);
    
    console.log(myObject.name); // 'John'
    console.log(myObject.age);  // 30
    
  • 创建具有特定原型的新对象: 通过结合 Object.create()Object.setPrototypeOf(),可以创建具有特定原型的新对象。

    const newPrototype = { age: 30 };
    const myObject = Object.create(newPrototype);
    
    console.log(myObject.age);  // 30
    

需要注意的是,改变对象的原型可能会导致一些不可预测的行为,并且在性能上可能产生一些开销。通常情况下,最好在对象创建时就确定其原型,而不·是在运行时动态更改。

1.20 Object.values()

在 JavaScript 中,Object.values() 是一个用于获取对象自身可枚举属性值的方法。它返回一个包含对象所有可枚举属性值的数组。

用法

Object.values() 的语法如下:

Object.values(obj);
  • obj: 要获取可枚举属性值的对象。

返回值

返回一个包含对象自身可枚举属性值的数组。

示例

const myObject = {
    name: 'John',
    age: 30,
    city: 'New York'
};

const values = Object.values(myObject);

console.log(values);
// Output: [ 'John', 30, 'New York' ]

在上述示例中,Object.values() 用于获取 myObject 的可枚举属性值,然后返回一个包含这些属性值的数组。

用途

  • 获取对象的属性值: 当你需要获取对象的属性值并进行处理时,可以使用 Object.values()

    const myObject = {
        name: 'John',
        age: 30,
        city: 'New York'
    };
    
    const values = Object.values(myObject);
    
    values.forEach(value => {
        console.log(value);
    });
    
  • 将对象转换为值的数组: 通过 Object.values() 可以将对象转换为包含其所有可枚举属性值的数组。

    const myObject = {
        name: 'John',
        age: 30,
        city: 'New York'
    };
    
    const valuesArray = Object.values(myObject);
    
    console.log(valuesArray);  // [ 'John', 30, 'New York' ]
    

需要注意的是,Object.values() 只返回对象自身的可枚举属性值,不包括原型链上的属性。

2、对象原型的对象属性

2.1 hasOwnProperty()

hasOwnProperty 是 JavaScript 中的一个对象方法,用于检查对象是否包含指定名称的属性,并且这个属性是对象自身的属性,而不是继承自原型链的属性。

用法

hasOwnProperty() 的语法如下:

obj.hasOwnProperty(prop);
  • obj: 要检查属性的对象。
  • prop: 要检查的属性名称。

返回值

返回一个布尔值,表示对象是否包含指定名称的自身属性。

示例

const myObject = {
    name: 'John',
    age: 30,
    city: 'New York'
};

console.log(myObject.hasOwnProperty('name'));  // true
console.log(myObject.hasOwnProperty('toString'));  // false (继承自原型链)

在上述示例中,hasOwnProperty() 用于检查 myObject 是否包含名为 'name' 的自身属性,结果为 true。而对于 toString 属性,因为它是继承自原型链的属性,返回的结果为 false

用途

  • 检查对象是否包含指定属性: 主要用于确定对象是否包含指定名称的自身属性。

    const myObject = {
        name: 'John',
        age: 30,
        city: 'New York'
    };
    
    if (myObject.hasOwnProperty('age')) {
        console.log('myObject has age property.');
    } else {
        console.log('myObject does not have age property.');
    }
    
  • 遍历对象的自身属性: 可以结合 for...in 循环和 hasOwnProperty() 来遍历对象的自身属性。

    const myObject = {
        name: 'John',
        age: 30,
        city: 'New York'
    };
    
    for (const prop in myObject) {
        if (myObject.hasOwnProperty(prop)) {
            console.log(`${prop}: ${myObject[prop]}`);
        }
    }
    

需要注意的是,hasOwnProperty() 只会检查对象的自身属性,不会检查原型链上的属性。如果你需要检查所有属性,包括原型链上的属性,可以使用 in 操作符。

2.2 isPrototypeOf()

isPrototypeOf() 是 JavaScript 中的一个对象方法,用于检查一个对象是否是另一个对象的原型。该方法用于检查一个对象是否存在于另一个对象的原型链上。

用法

isPrototypeOf() 的语法如下:

prototypeObj.isPrototypeOf(object);
  • prototypeObj: 作为原型的对象。
  • object: 要检查其原型链的对象。

返回值

返回一个布尔值,表示 prototypeObj 是否是 object 的原型。

示例

const personPrototype = {
    sayHello: function() {
        console.log('Hello!');
    }
};

const john = Object.create(personPrototype);

console.log(personPrototype.isPrototypeOf(john));  // true

在上述示例中,personPrototypejohn 的原型,因此 personPrototype.isPrototypeOf(john) 返回 true

用途

  • 检查对象的原型链: 主要用于确定一个对象是否存在于另一个对象的原型链上。

    const personPrototype = {
        sayHello: function() {
            console.log('Hello!');
        }
    };
    
    const john = Object.create(personPrototype);
    
    if (personPrototype.isPrototypeOf(john)) {
        console.log('john is an instance of personPrototype.');
    } else {
        console.log('john is not an instance of personPrototype.');
    }
    
  • 判断对象的原型关系: 可以用于确定对象之间的原型关系。

    const animal = {
        breathe: function() {
            console.log('Breathing...');
        }
    };
    
    const dog = Object.create(animal);
    
    if (animal.isPrototypeOf(dog)) {
        console.log('dog is an instance of animal.');
    } else {
        console.log('dog is not an instance of animal.');
    }
    

需要注意的是,isPrototypeOf() 只能检查直接原型关系,而不是整个原型链。如果你需要检查整个原型链上的关系,可以通过其他手段,例如递归遍历原型链。

2.3 propertyIsEnumerable()

propertyIsEnumerable() 是 JavaScript 中的对象方法,用于检查指定属性是否是对象自身的可枚举属性。该方法返回一个布尔值,指示指定的属性是否可枚举并且是对象的自身属性。

用法

propertyIsEnumerable() 的语法如下:

obj.propertyIsEnumerable(prop);
  • obj: 要检查属性的对象。
  • prop: 要检查的属性名称。

返回值

返回一个布尔值,表示指定的属性是否是对象的自身可枚举属性。

示例

const myObject = {
    name: 'John',
    age: 30
};

console.log(myObject.propertyIsEnumerable('name'));  // true
console.log(myObject.propertyIsEnumerable('toString'));  // false (继承自原型链)

在上述示例中,propertyIsEnumerable() 用于检查 myObject 是否包含名为 'name' 的自身可枚举属性,结果为 true。对于 toString 属性,因为它是继承自原型链的属性,返回的结果为 false

用途

  • 检查属性是否可枚举: 主要用于确定指定的属性是否是对象自身的可枚举属性。

    const myObject = {
        name: 'John',
        age: 30
    };
    
    if (myObject.propertyIsEnumerable('name')) {
        console.log('name is an enumerable property of myObject.');
    } else {
        console.log('name is not an enumerable property of myObject.');
    }
    
  • 遍历对象的可枚举属性: 结合 for...in 循环和 propertyIsEnumerable(),可以遍历对象的可枚举属性。

    const myObject = {
        name: 'John',
        age: 30
    };
    
    for (const prop in myObject) {
        if (myObject.propertyIsEnumerable(prop)) {
            console.log(`${prop}: ${myObject[prop]}`);
        }
    }
    

需要注意的是,propertyIsEnumerable() 只会检查对象的自身可枚举属性,不会检查原型链上的属性。如果你需要检查所有属性,包括原型链上的属性,可以使用 in 操作符。

2.4 valueOf()

valueOf() 是 JavaScript 中的对象方法,用于返回对象的原始值。当对象被用于预期为原始值的上下文(例如进行算术运算)时,JavaScript 将自动调用 valueOf() 方法来获取对象的原始值。

用法

valueOf() 的语法如下:

obj.valueOf();
  • obj: 要获取原始值的对象。

返回值

返回对象的原始值。

示例

const myObject = {
    value: 42,
    valueOf: function() {
        return this.value;
    }
};

console.log(myObject.valueOf());  // 42

在上述示例中,myObject 定义了 valueOf 方法,该方法返回对象的 value 属性。

用途

  • 获取对象的原始值: 当对象被用于预期为原始值的上下文时,JavaScript 会自动调用 valueOf() 方法。

    const myObject = {
        value: 42,
        valueOf: function() {
            return this.value;
        }
    };
    
    const result = myObject + 10;
    
    console.log(result);  // 52
    
  • 自定义对象的原始值: 可以通过定义 valueOf() 方法来自定义对象在预期为原始值的上下文中的行为。

    const customObject = {
        counter: 0,
        valueOf: function() {
            return this.counter++;
        }
    };
    
    console.log(customObject + 10);  // 10
    console.log(customObject + 10);  // 11
    

需要注意的是,valueOf() 方法主要用于对象在原始值上下文中的行为,但在某些情况下,JavaScript 引擎可能会忽略 valueOf(),转而调用 toString() 方法。因此,为了确保稳定的行为,有时也需要重写 toString() 方法。

2.5 toString()

toString() 是 JavaScript 中的对象方法,用于返回表示对象的字符串。当对象被用于预期为字符串的上下文时,JavaScript 将自动调用 toString() 方法来获取对象的字符串表示形式。

用法

toString() 的语法如下:

obj.toString();
  • obj: 要获取字符串表示形式的对象。

返回值

返回对象的字符串表示形式。

示例

const myObject = {
    value: 42,
    toString: function() {
        return `The value is ${this.value}`;
    }
};

console.log(myObject.toString());  // "The value is 42"

在上述示例中,myObject 定义了 toString 方法,该方法返回一个字符串表示形式,包含对象的 value 属性。

用途

  • 获取对象的字符串表示形式: 当对象被用于预期为字符串的上下文时,JavaScript 会自动调用 toString() 方法。

    const myObject = {
        value: 42,
        toString: function() {
            return `The value is ${this.value}`;
        }
    };
    
    const result = 'Object: ' + myObject;
    
    console.log(result);  // "Object: The value is 42"
    
  • 自定义对象的字符串表示形式: 可以通过定义 toString() 方法来自定义对象在字符串上下文中的行为。

    const customObject = {
        counter: 0,
        toString: function() {
            return `Counter value: ${this.counter}`;
        }
    };
    
    console.log('String representation: ' + customObject);  // "String representation: Counter value: 0"
    

需要注意的是,如果同时定义了 valueOf() 方法和 toString() 方法,JavaScript 引擎在选择使用哪个方法时可能会取决于上下文。在一些情况下,可能会优先选择 valueOf() 方法。如果需要确保对象在字符串上下文中的行为,建议同时重写 valueOf()toString() 方法。