javascript基础系列之Object

Object 是 JavaScript 的一种数据类型。它用于存储各种键值集合和更复杂的实体。

Object函数对象和实例对象

删除对象属性 delete

1
2
3
4
5
6
const obj = {
a: 1,
b: 2
}
delete obj.a;
console.log(obj); // {b: 2}

静态方法

Object.assign
1
2
3
4
5
// Object.assign(target, source1, source2, ...) 合并对象(浅拷贝)
const target = {a: 1};
const source = {b: 2};
Object.assign(target, source);
console.log(target); // {a: 1, b: 2}
Object.create
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Object.create 使用指定的原型对象和属性创建新对象
const parent = {
name: 'alan',
fn: function(){
console.log(this.name);
console.log(this.habit);
}
}
const obj = Object.create(parent); // 现有对象的__proto__指向parent
console.log(obj.__proto__ === parent); // true 现有对象的__proto__指向parent
obj.name = 'alan1';
obj.habit = "basketball";
obj.fn(); // alan1 basketball, 实例的原型是Parent
console.log(obj);
Object.defineProperty
1
2
3
4
5
6
7
8
9
10
// Object.defineProperty 给对象添加一个属性并指定该属性的配置
const obj = {};
Object.defineProperty(obj, "a", {
value: 1,
configurable: true,
writable: true,
enumerable: true
})

console.log(obj); // {a: 1}
Object.defineProperties
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Object.defineProperties 给对象添加多个属性并指定属性的配置
const obj1 = {};
Object.defineProperties(obj1, {
"prop1": {
value: 2,
writable: true,
enumerable: true,
configurable: true
},
"prop2": {
value: 3,
writable: true,
enumerable: true,
configurable: true
}
});
console.log(obj1); // {prop1: 2, prop2: 3}
Object.entries
1
2
3
4
5
6
7
8
// Object.entries 返回给定对象自身可枚举属性的[key, value]的数组
const obj = {
a: 1,
b: 2
}
for (const [key, value] of Object.entries(obj)) {
console.log(`key=${key}, value=${value}`); //a 1, b 2
}
Object.freeze
1
2
3
4
5
6
7
// Object.freeze 冻结对象,不能删除或者更改任何属性
const obj = {
a: 1
}
Object.freeze(obj); // 冻结对象
obj.a = 2;
console.log(obj.a); // 1
Object.getOwnPropertyDescriptor
1
2
3
4
5
6
// Object.getOwnPropertyDescriptor 返回对象的属性配置
const obj = {
a: 1
}
const desc = Object.getOwnPropertyDescriptor(obj, 'a');
console.log(desc); // {value: 1, writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyNames, Object.getOwnPropertySymbols, Object.getPrototypeOf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Object.getOwnPropertyNames, Object.getOwnPropertySymbols, Object.getPrototypeOf
const proto = {
a: 1,
b: 2,
[Symbol("a")]: "hello"
}
const obj = {
a: 3,
c: 4,
[Symbol("b")]: "world"
}
console.log(Object.getOwnPropertyNames(obj)); // ['a', 'c'] 包括对象自身所有属性(也包括不可枚举属性)的键名,不包含Symbol属性s
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(b)] 包含对象自身的所有Symbol属性的键名
Object.setPrototypeOf(obj, proto); // 设置obj的原型对象proto
console.log(Object.getPrototypeOf(obj)); //{a: 1, b: 2, Symbol(a): 'hello'} 获取obj的原型对象proto
Object.is
1
2
3
4
5
// Object.is  判断两个值是否相等,类似全等===,区别在于+0和-0,和NaN对比
console.log(+0 === -0); // true
console.log(Object.is(+0, -0)); // false
console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true
Object.isExtensible
1
2
3
4
5
6
7
8
9
10
11
12
// Object.isExtensible 判断对象是否可扩展
const obj = {};
console.log(Object.isExtensible(obj)); // true
Object.preventExtensions(obj); // 变的不可扩展,让一个对象变的不可扩展,永远不能添加新的属性
console.log(Object.isExtensible(obj)); // false

const sealed = Object.isSealed({}); // 密封对象是不可扩展的
console.log(Object.isExtensible(sealed)); // false
const obj1 = {};
console.log(Object.isExtensible(obj1)); // true
Object.freeze(obj1);
console.log(Object.isExtensible(obj1)); // false
Object.isFrozen
1
2
3
4
5
// Object.isFrozen  判断对象是否被冻结
const obj = {};
console.log(Object.isFrozen(obj)); // false
Object.freeze(obj);
console.log(Object.isFrozen(obj)); // true
Object.isSealed,Object.preventExtensions,Object.seal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Object.isSealed 判断对象是否密封
// Object.preventExtensions 让一个对象变的不可扩展,永远不能添加新的属性
// Object.seal 封闭对象,阻止添加新属性并将所有的现有属性标记为不可配置

// Object.preventExtensions({}),Object.preventExtensions和Object.defineProperty,Object.seal
const obj = { a: 1 };
console.log(Object.isSealed(obj)); // false
Object.seal(obj);
// Object.preventExtensions(obj); // 可以和Object.defineProperty配合实现对象密封
// Object.defineProperty(obj, 'a', { // 配合Object.preventExtensions实现对象密封
// configurable: false
// });
console.log(Object.isSealed(obj)); // true
// Object.keys
var obj = {
a: 1,
b: 2
}
console.log(Object.keys(obj)); // ['a','b'] 返回自身所有可遍历属性的键名的数组
Object.preventExtensions
1
2
3
4
5
6
7
// Object.preventExtensions 让一个对象变的不可扩展,永远不能添加新的属性
const obj = {
a: 1
}
Object.preventExtensions(obj);
obj.b = 2;
console.log(obj); // { a: 1} 属性b添加失败
Object.setPrototypeof
1
2
3
4
5
6
7
8
9
10
11
12
// Object.setPrototypeof 设置对象的原型
const proto = {
a: "hello"
}
const obj = {
a: "world",
find(){
return super.a; // super指向当前对象的原型对象
}
}
Object.setPrototypeOf(obj, proto);
console.log(obj.find()); // hello
Object.values
1
2
3
4
5
6
// Object.values 返回给定对象自身可枚举值的数组
var obj = {
a: 1,
b: 2
}
console.log(Object.values(obj)); // [1,2] 返回自身所有可遍历属性的键对应值的数组

实例属性

Object.prototype.constructor

1
2
// Object.prototype.constructor  指向Object构造函数
console.log(Object.prototype.constructor === Object); // true

Object.prototype.proto

1
2
3
// Object.prototype.__proto__ 指向构造函数Object的原型
const obj = {};
console.log(obj.__proto__ === Object.prototype); // true

实例方法

Object.prototype.defineGetter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// Object.prototype.__defineGetter__ 将函数(fn)绑定在当前对象的指定属性(obj.num)上,当获取对象属性时,函数会被调用
// 非标准,后面可能被废弃,推荐使用get语法(计算出来的属性)和Object.defineProperty
const obj = {
a: 1,
b: 2s
};
obj.__defineGetter__("num", function fn(){
return this.a + this.b;
});
console.log(obj.num); // 3

// 在对象字面量使用get语法, 它是一个计算出来的属性(动态的)
const obj1 = {
a: 3,
b: 4,
get num() { // 它是一个计算出来的属性(动态的)
return this.a + this.b;
}
}
console.log(obj1.num); // 7

// Object.defineProperty
const obj2 = {
a: 5,
b: 6
};
Object.defineProperty(obj2, "num", {
get: function(){ // 它是一个计算出来的属性(动态的)
return this.a + this.b;
}
});
console.log(obj2.num); // 11

Object.prototype.defineSetter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Object.prototype.__defineSetter__ 将函数绑定在当前对象的指定属性,当对象属性被赋值时,所绑定的函数会被调用
const obj = {};
obj.__defineSetter__("a", function(val) {
console.log(val); // 10
return 10;
});
obj.a = 20;

// es6 setter语法
const obj = {
arr: [],
set num(val) { // 设置num属性会调用set语法函数
this.arr.push(val);
}
}
obj.num = 10;
obj.num = 11;
console.log(obj.arr); // [10,11]

Object.prototype.lookupGetter

1
2
3
4
5
6
7
8
9
// Object.prototype.__lookupGetter__ (非标准)返回属性读取访问器函数(getter),
// 标准方式 Object.getOwnPropertyDescriptor
const obj = {
get habit() {
return Math.random() > 0.5 ? "apple" : "banana";
}
}
console.log(obj.__lookupGetter__("habit")); // ƒ habit() { return Math.random() > 0.5 ? "apple" : "banana";}
console.log(Object.getOwnPropertyDescriptor(obj, "habit").get); // 推荐使用,替代__lookupGetter__的标准方法

Object.prototype.lookupSetter

1
2
3
4
5
6
7
8
9
// Object.prototype.__lookupSetter__
const obj1 = {
name: "",
set habit(val) {
this.name = val;
}
}
console.log(obj1.__lookupSetter__("habit")); // habit(val) { this.name = val;}
console.log(Object.getOwnPropertyDescriptor(obj1, "habit").set); // 推荐使用,替代__lookupSetter__的标准方法

Object.prototype.hasOwnProperty

1
2
3
4
5
6
// Object.prototype.hasOwnProperty 对象自身是否具有某个属性,返回布尔值
const obj = {
a: 1
}
console.log(obj.hasOwnProperty("a")); // true
console.log(obj.hasOwnProperty("toString")); // false

Object.prototype.isPrototypeOf

1
2
3
4
5
6
7
 // Object.prototype.isPrototypeOf 检查一个对象是否存在于另一个对象的原型链上
function Foo(){}
function Bar(){}
Bar.prototype = Object.create(Foo.prototype); // Foo.prototype作为Bar的原型
const bar = new Bar();
console.log(Foo.prototype.isPrototypeOf(bar)); // bar对象的原型链中是否能找到Foo对象, bar.__proto__.__proto__ === Foo.prototype
console.log(Object.prototype.isPrototypeOf(bar)); // Object是否在bar的原型链上,Object在所有对象的原型链上

Object.prototype.propertyIsEnumerable

1
2
3
4
5
6
7
8
// Object.prototype.propertyIsEnumerable 表示指定属性是否可枚举
const obj = {
a: 1
}
const arr = [1];
console.log(obj.propertyIsEnumerable("a")); //true
console.log(arr.propertyIsEnumerable(0)); // true
console.log(arr.propertyIsEnumerable("length")); // false

Object.prototype.toLocaleString和toString

1
2
3
4
5
6
// Object.prototype.toLocaleString和toString  返回对象的字符串表示,和toString的主要区别是对日期处理
const obj = {a: 1};
const date = new Date();
console.log(obj.toLocaleString()); // [object Object]
console.log(date.toString()); // Thu Mar 10 2022 17:16:23 GMT+0800 (中国标准时间)
console.log(date.toLocaleString()); // 2022/3/10 17:16:23

Object.prototype.valueOf

1
2
3
4
5
6
7
// Object.prototype.valueOf 返回指定对象的原始值,大部分继承Object的对象都继承链该方法
const obj = {a: 1};
const date = new Date();
function fn() {}
console.log(obj.valueOf()); // {a:1}
console.log(fn.valueOf()); // ƒ fn() {}
console.log(date.valueOf()); // 1646903976014 时间戳

参考文档

Object