「Object.defineProperty」 深入浅出
# Object.defineProperty是什么?
Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
# 语法
Object.defineProperty(obj, prop, descriptor)
1
参数
obj
要定义属性的对象。
prop
要定义或修改的属性的名称。
descriptor
要定义或修改的属性描述符。
返回值
- 被传递给函数的对象。
# 示例
# 返回值
let obj1 = {
name: "张三",
};
Object.defineProperty(obj1, "name", {
value: "李四",
});
console.log(obj1);//{name: '李四'}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 添加新的属性
- configurable 可配置的
- writable 可写的
- enumerable 可枚举的
这仨属性是默认是false
的 让我们先来演示一遍。
let obj1 = {
name: "张三",
};
Object.defineProperty(obj1, "age", {
value: 24,
configurable: false,
writable: false,
enumerable: false,
});
console.log(obj1); //{name: '张三', age: 24}
//修改属性
obj1.age = 26;
console.log(obj1); //{name: '张三', age: 24}
//删除属性
delete obj1.age;
console.log(obj1); //{name: '张三', age: 24}
//for in 遍历
for (let i in obj1) {
console.log(obj1[i]); //只打印了张三
}
//通过Object.key()来获取键 获取不到
console.log(Object.keys(obj1)); //['name']
//如果我们就是想获取里面的属性名怎么办呢 可以通过getOwnPropertyNames来获取自身的属性
console.log(Object.getOwnPropertyNames(obj1)); //['name', 'age']
//或者我们用来判断自身有没有age这个属性 可以通过hasOwnProperty来判断是否存在
console.log(obj1.hasOwnProperty("age")); //true
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
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
这仨设置为true重复上面操作,发现都是你想要的结果了。
# get和set
因为get
和set
的劫持 增加了操作的灵活性,可以在get、set
方法里进行一些操作。
let obj1 = {
name: "张三",
};
let value = null;
Object.defineProperty(obj1, "name", {
get() {
console.log("get!");
return value;
},
set(newVal) {
console.log("set!");
value = newVal;
},
});
obj1.name;//get!
obj1.name = "李四";// 'set!'
console.log(obj1.name); //李四
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
下面的例子展示了如何实现一个自存档对象。当设置temperature 属性时,archive 数组会收到日志条目。
function Archiver() {
var temperature = null;
var archive = [];
Object.defineProperty(this, "temperature", {
get() {
return temperature;
},
set(value) {
temperature = value;
archive.push(temperature);
},
});
this.getArchive = function () {
return archive;
};
}
var arc = new Archiver();
arc.temperature = 11;
arc.temperature = 12;
console.log(arc.getArchive()); // [11, 12]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 描作符存在异常的情况
如果一个描述符同时拥有value
或 writable
和 get
或 set
键,则会产生一个异常。
- 也就说
value
或writable
出现的地方,get
或set
都不能出现 get
或set
出现的地方,value
或writable
都不能出现- 否则就会抛出一个异常
let obj1 = {};
Object.defineProperty(obj1, "name", {
value: "张三",
get() {},
});
//Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute
1
2
3
4
5
6
2
3
4
5
6
# 继承
一个不可写的属性被继承的话 继承过来之后还是不可写!
function Person() {}
Person.prototype.name = "张三";
Object.defineProperty(Person.prototype, "age", {
writable: false,
value: 8,
});
let p1 = new Person();
p1.name = "李四";
p1.age = 10;
p1.hobby = "Games";
console.log(p1); //{name: '李四', hobby: 'Games'}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 与Object.defineProperties的区别
# Object.defineProperties语法
该方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象,和Object.defineProperty
类似,但参数不同
Object.defineProperties(obj, props)
1
# 区别
Object.defineProperties可以操作一个对象新增或修改多个属性
let sample1 = {};
Object.defineProperties(sample1, {
prop1: {
value: "Jerry",
configurable: false,
writable: false,
enumerable: false,
},
prop2: {
value: "Tom",
configurable: false,
writable: false,
enumerable: false,
},
});
sample1.prop1 = "Nacy";
sample1.prop2 = "Nacy";
console.log(sample1.prop1); //Jerry
console.log(sample1.prop2); //Tom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 经典面试题
请在控制台打印'今天吃🍔'
if (a === 1 && a === 2 && a === 3) {
console.log("success");
}
1
2
3
2
3
答案
let i = 1;
Object.defineProperty(window, "a", {
get() {
return i++;
},
});
每次调用a的时候都会走到get方法里面,返回i++
if (a === 1 && a === 2 && a === 3) {
console.log("今天吃🍔");
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
上次更新: 2022/12/21, 14:57:33