原型链的实例属性(2个)
1.Object.prototype.constructor
constructor属性表示创建某个对象实例的构造函数。每个 JavaScript 对象都会从其原型中继承这个属性。
作用
- 确定某个对象是由哪个构造函数创建的。
- 在对象实例上创建新的实例。
代码示例
//确定某个对象是由哪个构造函数创建的。
const obj = {};
console.log(obj.constructor === Object); // true
const arr = [];
console.log(arr.constructor === Array); // true
const num = new Number(42);
console.log(num.constructor === Number); // true
//创建新的实例
function Person(name) {
this.name = name;
}
const person1 = new Person("Alice");
console.log(person1.constructor === Person); // true
2.Object.prototype.__proto__(已弃用)
Object.prototype.proto 是一个 JavaScript 对象的访问器属性,用于访问和设置对象的内部 [[Prototype]] 属性,即该对象的原型。(原型对象是用于定义该对象属性和方法的模板)
目前推荐使用Object.getPrototypeOf() 和 Object.setPrototypeOf() 来获取和设置对象的原型,
作用
- 获取原型:可以通过
__proto__访问对象的原型。 - 设置原型:可以通过
__proto__设置对象的原型。
代码示例
//获取对象的原型
const obj = { a: 1 };
const prototype = obj.__proto__;
console.log(prototype === Object.prototype); // true
//设置对象的原型
const prototype = { b: 2 };
const obj = {};
obj.__proto__ = prototype;
console.log(obj.b); // 2
注意:
- 设置对象的原型时。提供的值必须是一个对象或
null,任何其他值都不会产生作用。 - 对于原型为 null 的对象,proto 的值是 undefined。任何对 proto 的赋值操作都会在对象上创建一个名为 proto 的新属性,而不会改变对象的原型
原型链的实例方法(6个)
1.Object.prototype.hasOwnProperty()
用于检查该属性是否是对象的自身属性(非继承属性)
语法
obj.hasOwnProperty(prop)
- 参数:
prop是一个字符串,表示要检查的属性的名称。 - 返回值:如果对象具有指定的自身属性,则返回
true,否则返回false。
代码示例
const obj = {
a: 1,
b: 2
};
console.log(obj.hasOwnProperty('a')); // true
console.log(obj.hasOwnProperty('b')); // true
console.log(obj.hasOwnProperty('c')); // false
注意:
1。 该方法为原型链方法,使用该方法的对象必须继承自 Object.prototype ,否则不能使用。
2.Object.prototype.isPrototypeOf()
用于检查一个对象是否存在于另一个对象的原型链中
语法
Object.prototype.isPrototypeOf(object)
参数
object:要检查的对象,看它是否在调用isPrototypeOf()方法的对象的原型链上。
返回值:
- 当参数是 undefined 或者 null 时,返回false
- 如果调用该方法的对象是指定对象的原型或位于其原型链上,则返回
true,否则返回false。
代码示例
function Person(name) {
this.name = name;
}
const person1 = new Person('Alice');
console.log(Person.prototype.isPrototypeOf(person1)); // true
3.Object.prototype.propertyIsEnumerable()
用于检查指定属性是否能够通过
for...in循环枚举,并且是否是对象的自身属性
语法
Object.prototype.propertyIsEnumerable(prop)
参数:
prop:一个字符串,表示要检查的属性的名称。
返回值:
- 如果对象具有指定的可枚举属性(即该属性存在于对象本身而不是继承自原型链,并且可以通过
for...in循环访问),则返回true。否则返回false。
代码示例
const obj = {
a: 1,
b: 2
};
console.log(obj.propertyIsEnumerable('a')); // true
console.log(obj.propertyIsEnumerable('b')); // true
console.log(obj.propertyIsEnumerable('toString')); // false,toString 方法不可枚举
4.Object.prototype.valueOf()
Object.prototype.valueOf()方法常用于将对象转换为原始值(基本数据类型)(例如数学运算、比较操作等)就常常会自动调用该方法。
返回值
一般情况下,它返回对象本身,但对于某些内置对象类型,如 Number、String 和 Date,它会返回相应的原始值。
示例
// 创建一个自定义对象
const obj = {
value: 10,
valueOf: function() {
return this.value;
}
};
// 当对象被用作数学运算的操作数时
const sum = obj + 5; // 调用 obj.valueOf() 获取原始值,然后进行加法运算
console.log(sum); // 输出: 15
// 在比较操作中使用
const isEqual = obj === 10; // 调用 obj.valueOf() 获取原始值,然后进行比较
console.log(isEqual); // 输出: true
// 显式调用 valueOf()
const primitiveValue = obj.valueOf();
console.log(primitiveValue); // 输出: 10
//返回当前时间戳
const date = new Date();
console.log(date.valueOf()); // 返回当前时间的时间戳
5.Object.prototype.toString()
用于获取对象的字符串表示的方法
语法
Object.prototype.toString()
返回值
toString() 方法返回一个表示该对象的字符串。
代码示例
const obj = [];
console.log(Object.prototype.toString.call(obj)); // 输出 "[object Array]"
const func = function() {};
console.log(Object.prototype.toString.call(func)); // 输出 "[object Function]"
const date = new Date();
console.log(Object.prototype.toString.call(date)); // 输出 "[object Date]"
const nullValue = null;
console.log(Object.prototype.toString.call(nullValue)); // 输出 "[object Null]"
const objWithCustomPrototype = Object.create({});
console.log(Object.prototype.toString.call(objWithCustomPrototype)); // 输出 "[object Object]"
注意
1.在调用 obj.toString()时我们需要带上(.call(obj)),这样才能把this指向我们的参数,返回参数的toString()而不是对象自身的 toString() 方法
6.Object.prototype.toLocaleString()
相比于
toString()来说,toLocaleString()的返回值会根据提供的地区设置(locale)而变化,并可能包含地区特定的格式和符号。而toString()的返回值通常是一个更通用的、不依赖于地区设置的字符串表示。
语法
Object.prototype.toLocaleString()
语法
toLocaleString()方法返回一个表示对象本地化字符串的值。对于大多数内置对象,这个方法返回的值与toString()方法返回的值相同。
代码示例
const obj = {
toString() {
return 'Object';
},
toLocaleString() {
return 'Localized Object';
}
};
console.log(obj.toString()); // Object
console.log(obj.toLocaleString()); // 本地化Object
静态方法(22个)
1.Object.assign()
用于将一个或多个源对象的所有可枚举属性复制到目标对象中。它返回目标对象。
语法
Object.assign(target, ...sources)
- target:目标对象。
- sources:一个或多个源对象。
代码示例
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target); // { a: 1, b: 4, c: 5 }
console.log(returnedTarget); // { a: 1, b: 4, c: 5 }
注意事项
- 浅拷贝:
Object.assign()执行的是浅拷贝。如果源对象中的属性是对象(引用类型),则只会复制其引用。 - 同名属性覆盖:如果多个源对象有相同的属性名,后面的属性会覆盖前面的属性。
- 属性描述符:
Object.assign()只拷贝源对象的可枚举和自有属性。它不会拷贝继承的属性或不可枚举的属性。
示例:浅拷贝和深拷贝的区别
const obj = { a: 1, b: { c: 2 } };
const shallowCopy = Object.assign({}, obj);
shallowCopy.b.c = 3;
console.log(obj.b.c); // 3, 浅拷贝影响了原对象
// 深拷贝可以使用 JSON 方法(但是注意这只适用于不包含函数的对象)
const deepCopy = JSON.parse(JSON.stringify(obj));
deepCopy.b.c = 4;
console.log(obj.b.c); // 3, 深拷贝不影响原对象
2.Object.create()
用于创建一个新对象,并且这个新对象的原型(
[[Prototype]])由你指定。你还可以通过可选的属性描述符来进一步定义这个新对象的属性。
语法
Object.create(proto, [propertiesObject])
- proto:新创建对象的原型对象,可以为
null。 - propertiesObject(可选):一个对象,其属性将被添加到新创建的对象中,这些属性的描述符是使用
Object.defineProperties的格式。
代码示例
const person = {
isHuman: false,
printIntroduction: function() {
console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
}
};
const me = Object.create(person);
me.name = 'Matthew'; // "name" 属性是直接添加到 "me" 对象上,而不是在原型上
me.isHuman = true; // 继承的属性可以被覆盖
me.printIntroduction(); // My name is Matthew. Am I human? true
//使用 `null` 作为原型
const obj = Object.create(null);
console.log(Object.getPrototypeOf(obj)); // null
//带属性描述符的用法
const obj = Object.create({}, {
foo: {
value: 42,
writable: true,
configurable: true,
enumerable: true
},
bar: {
value: 'hello',
writable: false,
configurable: false,
enumerable: false
}
});
console.log(obj.foo); // 42
console.log(obj.bar); // hello
使用场景
- 创建具有特定原型的新对象:在创建对象时,可以指定它的原型,从而实现继承。
- 模拟类和继承:在 JavaScript 中实现基于原型的继承。
- 创建空对象:创建没有继承链的对象(如
Object.create(null))。
注意事项
- 性能:直接使用
Object.create(null)创建的对象没有原型,因此它的性能可能比常规对象更好,适合用作纯数据对象,如字典。 - 属性描述符:在创建对象时,可以通过属性描述符进一步定义对象的属性。
3.Object.defineProperty()
用于在对象上定义或修改一个属性,并返回该对象。
语法
Object.defineProperty(obj, prop, descriptor)
- obj:要在其上定义属性的对象。
- prop:要定义或修改的属性的名称。
- descriptor:将被定义或修改的属性描述符。
属性描述符
属性描述符分为两类:数据描述符和访问器描述符。一个描述符只能是这两者之一,不可混合。
数据描述符
- value:属性的值,默认为
undefined。 - writable:表示属性的值是否可以被修改,默认为
false。 - enumerable:表示属性是否可以通过
for...in循环枚举,默认为false。 - configurable:表示属性描述符是否可以被修改,属性是否可以被删除,默认为
false。
访问器描述符
- get:一个给属性提供 getter 的函数,如果没有 getter 则为
undefined。 - set:一个给属性提供 setter 的函数,如果没有 setter 则为
undefined。 - enumerable:表示属性是否可以通过
for...in循环枚举,默认为false。 - configurable:表示属性描述符是否可以被修改,属性是否可以被删除,默认为
false。
代码示例
//基本用法
const obj = {};
Object.defineProperty(obj, 'a', {
value: 1,
writable: true,
enumerable: true,
configurable: true
});
console.log(obj.a); // 1
//定义一个只读属性
const obj = {};
Object.defineProperty(obj, 'a', {
value: 1,
writable: false
});
obj.a = 2; // 无效
console.log(obj.a); // 1
//定义一个访问器属性
const obj = {};
let value = 0;
Object.defineProperty(obj, 'b', {
get() {
return value;
},
set(newValue) {
value = newValue;
},
enumerable: true,
configurable: true
});
obj.b = 3;
console.log(obj.b); // 3
使用场景
- 精确控制属性行为:通过属性描述符,你可以精确控制属性的行为,如是否可枚举、可配置、可写。
- 实现只读属性:通过设置
writable: false,可以创建一个只读属性。 - 定义 getter 和 setter:可以使用
get和set方法定义访问器属性。
注意事项
- 默认值:如果没有显式指定,属性描述符中的所有字段默认为
false或undefined。 - 不可配置属性:一旦属性被定义为不可配置(
configurable: false),你就无法再修改它的可配置性和可枚举性。
4.Object.defineProperties()
用于一次性在一个对象上定义或修改多个属性。它会返回修改后的对象。这个方法与
Object.defineProperty()类似,但是区别是Object.defineProperties()允许我们在一个调用中定义多个属性。
语法
Object.defineProperties(obj, props)
- obj:要在其上定义属性的对象。
- props:一个对象,其每个属性对应于要定义或修改的属性及其描述符。
属性描述符
属性描述符分为数据描述符和访问器描述符。一个描述符只能是这两者之一,不可混合。
数据描述符
- value:属性的值,默认为
undefined。 - writable:表示属性的值是否可以被修改,默认为
false。 - enumerable:表示属性是否可以通过
for...in循环枚举,默认为false。 - configurable:表示属性描述符是否可以被修改,属性是否可以被删除,默认为
false。
访问器描述符
- get:一个给属性提供 getter 的函数,如果没有 getter 则为
undefined。 - set:一个给属性提供 setter 的函数,如果没有 setter 则为
undefined。 - enumerable:表示属性是否可以通过
for...in循环枚举,默认为false。 - configurable:表示属性描述符是否可以被修改,属性是否可以被删除,默认为
false。
代码示例
const obj = {};
Object.defineProperties(obj, {
'property1': {
value: 42,
writable: true,
enumerable: true,
configurable: true
},
'property2': {
value: 'hello',
writable: false,
enumerable: false,
configurable: false
}
});
console.log(obj.property1); // 42
console.log(obj.property2); // hello
//定义数据属性和访问器属性
const obj = {};
let value = 0;
Object.defineProperties(obj, {
'property1': {
value: 42,
writable: true,
enumerable: true,
configurable: true
},
'property2': {
get() {
return value;
},
set(newValue) {
value = newValue;
},
enumerable: true,
configurable: true
}
});
console.log(obj.property1); // 42
obj.property2 = 33;
console.log(obj.property2); // 33
使用场景
- 定义多个属性:在一个调用中定义或修改多个属性,简化代码。
- 统一管理属性描述符:方便地对一个对象的多个属性进行精细控制。
注意事项
- 默认值:如果没有显式指定,属性描述符中的所有字段默认为
false或undefined。 - 不可配置属性:一旦属性被定义为不可配置(
configurable: false),你就无法再修改它的可配置性和可枚举性。
5.Object.getOwnPropertyDescriptor()
用于获取指定对象上某个自有属性(即对象自身具有的属性,而不是从原型链上继承的属性)的属性描述符。它会返回描述符以对象的形式,该对象包含了该属性的配置。
语法
Object.getOwnPropertyDescriptor(obj, prop)
- obj:要查找的对象。
- prop:要获取其描述符的属性的名称。
返回值
返回一个对象形式的属性描述符,如果对象上不存在指定属性,则返回 undefined。
数据描述符
- value:属性的值。
- writable:表示属性的值是否可以被修改。
- enumerable:表示属性是否可以通过
for...in循环枚举,默认为false。 - configurable:表示属性描述符是否可以被修改,属性是否可以被删除,默认为
false。
访问器描述符
- get:属性的 getter 函数。
- set:属性的 setter 函数。
- enumerable:表示属性是否可以通过
for...in循环枚举,默认为false。 - configurable:表示属性描述符是否可以被修改,属性是否可以被删除,默认为
false。
代码示例
//获取数据属性的描述符
const obj = {
a: 42
};
const descriptor = Object.getOwnPropertyDescriptor(obj, 'a');
console.log(descriptor);
// 输出:{ value: 42, writable: true, enumerable: true, configurable: true }
//获取访问器属性的描述符
const obj = {};
let value = 0;
Object.defineProperty(obj, 'b', {
get() {
return value;
},
set(newValue) {
value = newValue;
},
enumerable: true,
configurable: true
});
const descriptor = Object.getOwnPropertyDescriptor(obj, 'b');
console.log(descriptor);
// 输出:{ get: [Function: get], set: [Function: set], enumerable: true, configurable: true }
//属性不存在时返回 `undefined`
const obj = {
a: 42
};
const descriptor = Object.getOwnPropertyDescriptor(obj, 'b');
console.log(descriptor); // undefined
使用场景
- 检查属性的配置:在对属性进行修改之前,检查属性的当前配置。
- 调试和测试:在调试和测试代码时,了解属性的详细配置。
6.Object.getOwnPropertyDescriptors()
用于获取对象自身所有属性的描述符。它会返回一个对象,其中每个属性对应一个属性描述符对象。
语法
Object.getOwnPropertyDescriptors(obj)
- obj:要获取其属性描述符的对象。
返回值
返回一个对象,该对象包含指定对象自身所有属性的描述符。
属性描述符
属性描述符分为两类:数据描述符和访问器描述符。
数据描述符
- value:属性的值。
- writable:表示属性的值是否可以被修改。
- enumerable:表示属性是否会出现在对象的枚举属性中。
- configurable:表示属性描述符是否可以被修改,属性是否可以被删除。
访问器描述符
- get:一个给属性提供 getter 的函数,如果没有 getter 则为
undefined。 - set:一个给属性提供 setter 的函数,如果没有 setter 则为
undefined。 - enumerable:表示属性是否会出现在对象的枚举属性中。
- configurable:表示属性描述符是否可以被修改,属性是否可以被删除。
代码示例
//获取对象所有属性的描述符
const obj = {
a: 42,
get b() {
return 10;
}
};
const descriptors = Object.getOwnPropertyDescriptors(obj);
console.log(descriptors);
// 输出:
/*
{
a: { value: 42, writable: true, enumerable: true, configurable: true },
b: { get: [Function: get b], set: undefined, enumerable: true, configurable: true }
}
*/
使用场景
- 对象克隆:我们可以结合
Object.create()实现对象的浅拷贝。 - 对象扩展:将一个对象的属性及其描述符复制到另一个对象中。
- 调试和检查:获取对象的所有属性描述符,便于调试和检查属性配置。
示例扩展:与 Object.defineProperties() 结合使用
可以将一个对象的所有属性及其描述符复制到另一个对象中。
const source = {
a: 1,
get b() {
return this.a + 1;
}
};
const target = {};
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
console.log(target.a); // 1
console.log(target.b); // 2
7.Object.entries()
用于返回一个给定对象自身可枚举属性的键值对数组。数组中的每个元素都是一个包含两个元素的数组,第一个元素是属性键,第二个元素是属性值。
语法
Object.entries(obj)
- obj:要返回其可枚举属性的对象。
返回值
返回一个数组,其中每个元素都是一个 [key, value] 对,表示对象自身可枚举属性的键值对。
代码示例
const obj = {
a: 1,
b: 2,
c: 3
};
const entries = Object.entries(obj);
console.log(entries);
// 输出:[['a', 1], ['b', 2], ['c', 3]]
//处理数组,`Object.entries()` 可以处理数组,因为数组也是对象,数组的索引被视为键。
const arr = ['foo', 'bar', 'baz'];
const entries = Object.entries(arr);
console.log(entries);
// 输出:[['0', 'foo'], ['1', 'bar'], ['2', 'baz']]
使用场景
- 对象遍历:可以让我们方便地获取对象的键值对并进行遍历。
- 对象转换:可以将对象转换为其他数据结构,如
Map。
注意事项
- 仅限自身属性:
Object.entries()只会返回对象自身的可枚举属性,不包括继承的属性。 - 属性顺序:属性的顺序与通过
for...in循环遍历对象属性时的顺序一致。
10.Object.getOwnPropertySymbols()
用于获取对象自身所有的符号属性(
Symbol)的数组。与Object.getOwnPropertyNames()和Object.keys()不同,Object.getOwnPropertySymbols()专门用于获取符号属性,而不是字符串属性。
语法
Object.getOwnPropertySymbols(obj)
- obj:要获取其符号属性的对象。
返回值 返回一个数组,包含对象自身的所有符号属性。如果没有符号属性,则返回一个空数组。
代码示例
const symbol1 = Symbol('symbol1');
const symbol2 = Symbol('symbol2');
const obj = {
[symbol1]: 'value1',
[symbol2]: 'value2',
a: 1
};
const symbols = Object.getOwnPropertySymbols(obj);
console.log(symbols);
// 输出:[Symbol(symbol1), Symbol(symbol2)]
console.log(obj[symbols[0]]); // 输出:value1
console.log(obj[symbols[1]]); // 输出:value2
与 Object.getOwnPropertyNames() 和 Object.keys() 的比较
const symbol1 = Symbol('symbol1');
const obj = {
[symbol1]: 'value1',
a: 1,
b: 2
};
const keys = Object.keys(obj);
console.log(keys);
// 输出:['a', 'b']
const propertyNames = Object.getOwnPropertyNames(obj);
console.log(propertyNames);
// 输出:['a', 'b']
const symbols = Object.getOwnPropertySymbols(obj);
console.log(symbols);
// 输出:[Symbol(symbol1)]
使用场景
- 处理符号属性:在处理对象的符号属性时非常有用,因为符号属性不会被常规的属性枚举方法(如
Object.keys、for...in)获取到。 - 避免属性冲突:使用符号作为属性键可以避免属性名称冲突,尤其是在使用第三方库或扩展对象时。
11.Object.keys()
它会返回一个数组,该数组包含对象自身的可枚举属性的键(即属性名称)。这些键会以字符串的形式返回,并且只包括对象自身的属性,不包括从原型链上继承的属性。
语法
Object.keys(obj)
- obj:要返回其可枚举属性键的对象。
返回值
返回一个包含对象自身的可枚举属性键的数组。这些键是按顺序排列的,与 for...in 循环遍历对象属性时的顺序一致。
代码示例
const obj = {
a: 1,
b: 2,
c: 3
};
const keys = Object.keys(obj);
console.log(keys);
// 输出:['a', 'b', 'c']
处理数组
Object.keys() 可以用于数组,返回数组的索引作为键。
const arr = ['foo', 'bar', 'baz'];
const keys = Object.keys(arr);
console.log(keys);
// 输出:['0', '1', '2']
处理对象原型链
Object.keys() 只返回对象自身的可枚举属性,不包括继承的属性。
function Parent() {
this.inherited = 'inherited';
}
Parent.prototype.protoProp = 'protoProp';
const obj = new Parent();
obj.ownProp = 'ownProp';
const keys = Object.keys(obj);
console.log(keys);
// 输出:['inherited', 'ownProp']
使用场景
- 遍历对象属性:获取对象自身的可枚举属性键,并进行遍历操作。
- 对象操作:结合数组方法(如
map、forEach等),对对象属性进行各种操作。
示例扩展:遍历对象属性和值
可以结合 Array.prototype.forEach() 遍历对象的属性和值。
const obj = {
a: 1,
b: 2,
c: 3
};
Object.keys(obj).forEach(key => {
console.log(`${key}: ${obj[key]}`);
});
// 输出:
// a: 1
// b: 2
// c: 3
示例扩展:计算对象属性的个数
可以使用 Object.keys() 计算对象自身属性的个数。
const obj = {
a: 1,
b: 2,
c: 3
};
const count = Object.keys(obj).length;
console.log(count); // 输出:3
12.Object.values()
它会返回一个给定对象自身的所有可枚举属性值的数组。这些值按属性键的顺序排列,与
Object.keys()返回的键的顺序一致。
语法
Object.values(obj)
- obj:要返回其可枚举属性值的对象。
返回值
返回一个包含对象自身的可枚举属性值的数组。
代码示例
const obj = {
a: 1,
b: 2,
c: 3
};
const values = Object.values(obj);
console.log(values);
// 输出:[1, 2, 3]
结合 Object.keys() 和 Object.values() 可以遍历对象的属性和值。
const obj = {
a: 1,
b: 2,
c: 3
};
Object.keys(obj).forEach(key => {
console.log(`${key}: ${obj[key]}`);
});
// 输出:
// a: 1
// b: 2
// c: 3
使用场景
- 遍历对象属性值:获取对象自身的可枚举属性值,并进行遍历操作。
- 对象操作:结合数组方法(如
map、forEach等),对对象属性值进行各种操作。
13.Object.hasOwn()
用于检查对象自身(而不是从原型链上继承的)是否具有特定的属性。这个方法是 ES2022 (ECMAScript 2022) 引入的,它是
Object.prototype.hasOwnProperty()的一个简洁替代。
语法
Object.hasOwn(obj, prop)
- obj:要检查的对象。
- prop:要检查的属性名称。
返回值
返回一个布尔值,表示对象是否具有指定的自身属性。
代码示例
const obj = {
a: 1,
b: 2
};
console.log(Object.hasOwn(obj, 'a')); // true
console.log(Object.hasOwn(obj, 'b')); // true
console.log(Object.hasOwn(obj, 'c')); // false
使用场景
- 检查属性存在性:在处理对象属性时,检查对象是否具有某个自身属性,而不是继承的属性。
- 对象遍历:在遍历对象属性时,可以用来过滤掉继承的属性。
- 替代
hasOwnProperty():提供一个简洁的方法来代替hasOwnProperty()。
注意事项
Object.hasOwn()是 ES2022 引入的,可能在较旧的 JavaScript 环境中不被支持。在这种情况下,可以使用Object.prototype.hasOwnProperty.call(obj, prop)作为替代。
14.Object.is()
用于比较两个值是否严格相等。它与严格相等运算符
===的行为类似,但有几个特殊的区别,尤其是在处理特殊值(如NaN和-0)时。
语法
Object.is(value1, value2)
- value1:要比较的第一个值。
- value2:要比较的第二个值。
返回值
返回一个布尔值,表示两个值是否相等。
特殊情况
- NaN 相等性:
Object.is(NaN, NaN)返回true,而NaN === NaN返回false。 - -0 和 +0 相等性:
Object.is(-0, +0)返回false,而-0 === +0返回true。
代码示例
console.log(Object.is(1, 1)); // true
console.log(Object.is('foo', 'foo')); // true
console.log(Object.is({}, {})); // false (不同的引用)
console.log(Object.is(NaN, NaN)); // true
console.log(Object.is(-0, +0)); // false
使用场景
- 特殊值比较:在需要严格区分
NaN、-0和+0等特殊值时,使用Object.is()更为准确。 - 对象比较:当需要比较对象引用是否相同时,可以使用
Object.is()进行比较。
注意事项
Object.is()是 ECMAScript 6 引入的新方法,与传统的比较运算符(如==和===)有所不同,需要根据具体情况选择使用。
Object.is()与 === 的对比
console.log(Object.is(0, 0)); // true
console.log(0 === 0); // true
console.log(Object.is(-0, -0)); // true
console.log(-0 === -0); // true
console.log(Object.is(-0, 0)); // false
console.log(-0 === 0); // true
console.log(Object.is(NaN, NaN)); // true
console.log(NaN === NaN); // false
15.Object.getPrototypeOf()
用于返回指定对象的原型(即,内部
[[Prototype]]属性的值)。原型是对象继承属性和方法的机制。
语法
Object.getPrototypeOf(obj)
- obj:要返回其原型的对象。
返回值
返回指定对象的原型。如果对象没有继承属性(即其原型是 null),则返回 null。
代码示例
const obj = {};
const proto = Object.getPrototypeOf(obj);
console.log(proto === Object.prototype); // true
//自定义原型链
function Parent() {
this.parentProp = 'parent';
}
const child = new Parent();
console.log(Object.getPrototypeOf(child) === Parent.prototype); // true
//检查与内置对象的继承关系,检查对象是否继承自某个内置对象的原型。
const arr = [1, 2, 3];
console.log(Object.getPrototypeOf(arr) === Array.prototype); // true
const func = function() {};
console.log(Object.getPrototypeOf(func) === Function.prototype); // true
使用场景
- 对象原型检查:在开发和调试时,检查对象的原型链。
- 原型链操作:结合
Object.setPrototypeOf()修改对象的原型链。 - 继承关系检查:验证对象的继承关系。
注意事项
- 直接操作原型链(如使用
Object.setPrototypeOf())可能会影响性能,应该谨慎使用。 Object.getPrototypeOf()返回null表示对象没有原型,即对象不继承任何属性或方法。
16.Object.setPrototypeOf()
用于设置指定对象的原型(即,内部
[[Prototype]]属性的值)。它允许我们改变一个对象的原型链。
语法
Object.setPrototypeOf(obj, prototype)
- obj:要设置原型的对象。
- prototype:新原型对象,或者
null。
返回值
返回修改后的对象。
代码示例
const proto = {
greet() {
return 'Hello';
}
};
const obj = {
name: 'Alice'
};
Object.setPrototypeOf(obj, proto);
console.log(obj.greet()); // 输出 'Hello'
//设置为 `null`,意味着该对象将不再从任何原型继承属性和方法。
const obj = {};
Object.setPrototypeOf(obj, null);
console.log(Object.getPrototypeOf(obj)); // 输出 null
使用场景
- 改变原型链:在动态系统中,可能需要更改对象的原型以改变其行为。
- 对象组合:通过设置对象的原型,可以实现对象的组合与继承。
注意事项
- 性能影响:直接操作原型链可能会对性能造成负面影响,特别是在热代码路径中。
- 浏览器兼容性:
Object.setPrototypeOf是 ECMAScript 2015 (ES6) 引入的方法,较旧的浏览器可能不支持。 - 替代方法:可以使用
Object.create()创建一个具有指定原型的新对象,避免直接修改原型链。
17.Object.freeze()
用于冻结一个对象。被冻结的对象不能再被修改,即不能向其添加新的属性,不能删除已有属性,不能修改已有属性的可枚举性、可配置性、可写性,不能修改已有属性的值(如果属性的值是对象,该对象的属性也无法修改,除非它们也被冻结)。
语法
Object.freeze(obj)
- obj:要冻结的对象。
返回值
返回被冻结的对象。
代码示例
const obj = {
prop: 42
};
Object.freeze(obj);
obj.prop = 33; // 不能修改属性值
delete obj.prop; // 不能删除属性
console.log(obj.prop); // 输出 42
冻结嵌套对象 冻结是浅层的,意味着只冻结对象的直接属性。如果属性的值是另一个对象,那个对象不会被冻结,除非手动冻结。
const obj = {
internal: {
a: 1
}
};
Object.freeze(obj);
obj.internal.a = 42; // 可以修改内部对象的属性
console.log(obj.internal.a); // 输出 42
为了冻结嵌套对象,可以使用递归函数。
function deepFreeze(obj) {
Object.freeze(obj);
Object.keys(obj).forEach(key => {
if (typeof obj[key] === 'object' && obj[key] !== null) {
deepFreeze(obj[key]);
}
});
return obj;
}
const obj = {
internal: {
a: 1
}
};
deepFreeze(obj);
obj.internal.a = 42; // 不能修改内部对象的属性
console.log(obj.internal.a); // 输出 1
使用场景
- 常量对象:在开发中,将对象定义为常量,防止其被修改。
- 防止意外修改:确保对象的结构和内容在整个程序执行期间保持不变。
- 安全性:增强代码的安全性,防止对象被恶意篡改。
注意事项
- 不可逆:一旦对象被冻结,就无法解冻。
- 性能影响:冻结对象会有性能开销,尤其是在处理大量对象时。
- 浅冻结:
Object.freeze()是浅冻结,嵌套对象需要手动深冻结。
18.Object.isFrozen()
用于检查对象是否被冻结。被冻结的对象意味着它不能再被修改:不能添加新属性,不能删除已有属性,不能修改已有属性的值、可枚举性、可配置性或可写性。
语法
Object.isFrozen(obj)
- obj:要检查是否被冻结的对象。
返回值
返回一个布尔值,表示对象是否被冻结。
代码示例
const obj = {
prop: 42
};
console.log(Object.isFrozen(obj)); // 输出 false
Object.freeze(obj);
console.log(Object.isFrozen(obj)); // 输出 true
检查非对象类型
对于非对象类型(如字符串、数字等),Object.isFrozen() 方法会返回 true,因为它们本质上是不可变的。
console.log(Object.isFrozen(42)); // 输出 true
console.log(Object.isFrozen('Hello')); // 输出 true
使用场景
- 确认对象是否冻结:在操作对象前,可以确认对象是否被冻结,以避免修改失败。
- 调试和验证:在调试和验证代码时,确保对象在需要冻结的情况下确实被冻结了。
注意事项
- 浅冻结:
Object.freeze()只会浅冻结对象,对于嵌套对象,需要手动深冻结。 - 不可逆:一旦对象被冻结,就无法解冻。
20.Object.isExtensible()
用于检查对象是否是可扩展的。可扩展对象可以添加新的属性。默认情况下,所有对象都是可扩展的,除非使用了特定的方法来将其变为不可扩展。
语法
Object.isExtensible(obj)
- obj:要检查的对象。
返回值
返回一个布尔值,表示对象是否是可扩展的。
代码示例
const obj = {
prop: 42
};
console.log(Object.isExtensible(obj)); // 输出 true
Object.preventExtensions(obj);
console.log(Object.isExtensible(obj)); // 输出 false
使用Object.preventExtensions() 方法可以使对象变为不可扩展,即不能添加新的属性。
const obj = {
prop: 42
};
Object.preventExtensions(obj);
obj.newProp = 27; // 无法添加新属性
console.log(obj.newProp); // 输出 undefined
使用Object.freeze() 方法会使对象变为不可扩展,同时将所有现有属性的可配置性和可写性设置为 false。
const obj = {
prop: 42
};
Object.freeze(obj);
console.log(Object.isExtensible(obj)); // 输出 false
obj.newProp = 27; // 无法添加新属性
console.log(obj.newProp); // 输出 undefined
// 尝试修改属性值也会失败
obj.prop = 27;
console.log(obj.prop); // 输出 42
使用场景
- 检查对象是否可扩展:在需要确定对象是否可以添加新属性时使用。
- 调试和验证:确保对象在某些情况下保持不可扩展状态,避免意外的属性添加。
注意事项
- 不可逆:一旦对象变为不可扩展,就无法再变回可扩展。
- 属性的其他特性:
Object.preventExtensions()只会影响对象的可扩展性,而Object.seal()和Object.freeze()会进一步限制对象属性的配置。
21.Object.seal()
用于将一个对象密封,使其变为不可扩展的,并且将所有现有属性的可配置性(
configurable)设置为false。密封对象的现有属性仍然可以修改,但不能添加新属性或删除现有属性。
语法
Object.seal(obj)
- obj:要密封的对象。
返回值
返回密封后的对象。
代码示例
const obj = {
prop: 42
};
Object.seal(obj);
obj.prop = 33; // 可以修改现有属性的值
console.log(obj.prop); // 输出 33
obj.newProp = 27; // 无法添加新属性
console.log(obj.newProp); // 输出 undefined
delete obj.prop; // 无法删除现有属性
console.log(obj.prop); // 输出 33
检查对象是否已密封
可以使用 Object.isSealed() 方法来检查对象是否已密封。
const obj = {
prop: 42
};
console.log(Object.isSealed(obj)); // 输出 false
Object.seal(obj);
console.log(Object.isSealed(obj)); // 输出 true
与 Object.freeze() 的区别
Object.seal():将对象变为不可扩展,并将所有现有属性的可配置性设置为false。现有属性的值仍然可以修改。Object.freeze():在Object.seal()的基础上,还将所有现有属性的可写性(writable)设置为false,使得现有属性的值也不能修改。
示例对比
const sealedObj = {
prop: 42
};
Object.seal(sealedObj);
sealedObj.prop = 33; // 可以修改属性值
console.log(sealedObj.prop); // 输出 33
const frozenObj = {
prop: 42
};
Object.freeze(frozenObj);
frozenObj.prop = 33; // 无法修改属性值
console.log(frozenObj.prop); // 输出 42
使用场景
- 保护对象结构:在需要确保对象的结构(属性的存在性和数量)保持不变的情况下使用。
- 防止属性删除:确保对象的属性不会被意外删除。
- 调试和验证:用于调试和验证代码中对象的状态,确保对象不会被意外修改。
注意事项
- 不可逆:一旦对象被密封,就无法取消密封。
- 仅影响可配置性:
Object.seal()仅影响属性的可配置性,不影响属性的可写性。
22.Object.isSealed()
用于检查对象是否已经被密封。被密封的对象不可扩展,且其所有现有属性的可配置性(
configurable)都被设置为false,但属性值仍然可以修改。
语法
Object.isSealed(obj)
- obj:要检查的对象。
返回值
返回一个布尔值,表示对象是否被密封。
代码示例
const obj = {
prop: 42
};
console.log(Object.isSealed(obj)); // 输出 false
Object.seal(obj);
console.log(Object.isSealed(obj)); // 输出 true
尝试密封对象的影响
const obj = {
prop: 42
};
Object.seal(obj);
obj.prop = 33; // 可以修改现有属性的值
console.log(obj.prop); // 输出 33
obj.newProp = 27; // 无法添加新属性
console.log(obj.newProp); // 输出 undefined
delete obj.prop; // 无法删除现有属性
console.log(obj.prop); // 输出 33
检查密封对象的属性
可以通过 Object.getOwnPropertyDescriptor() 检查对象属性的描述符,验证属性是否不可配置。
const obj = {
prop: 42
};
Object.seal(obj);
const descriptor = Object.getOwnPropertyDescriptor(obj, 'prop');
console.log(descriptor.configurable); // 输出 false
console.log(descriptor.writable); // 输出 true
使用场景
- 确认对象是否被密封:在操作对象前,确保对象已经被密封,避免结构被修改。
- 调试和验证:用于调试和验证代码中的对象状态,确保对象的结构保持不变。
与 Object.preventExtensions() 和 Object.freeze() 的区别
Object.preventExtensions():使对象不可扩展,不能添加新属性,但可以删除或修改现有属性。Object.seal():在Object.preventExtensions()的基础上,所有现有属性的可配置性被设置为false,但现有属性的值仍然可以修改。Object.freeze():在Object.seal()的基础上,所有现有属性的可写性被设置为false,使得现有属性的值也不能修改。
示例对比
const obj1 = {
prop: 42
};
Object.preventExtensions(obj1);
console.log(Object.isSealed(obj1)); // 输出 false
const obj2 = {
prop: 42
};
Object.seal(obj2);
console.log(Object.isSealed(obj2)); // 输出 true
const obj3 = {
prop: 42
};
Object.freeze(obj3);
console.log(Object.isSealed(obj3)); // 输出 true