js 在赋值操作的时候很方便,不需要类型一致才能赋值,一个 “=” 就解决问题。但是也牵扯出问题,例如今天的例子用 “=” 给对象添加属性发生的事。
如果两个对象 A 和 B , B 的 prototype 指向 A 。那么在给 B 增加属性时,就会出现下列三种情况。
情况1:大多数情况
let A = { name: 1 };
let B = Object.create(A);
B.name = 2
console.log(A.name) // 1
console.log(B.name) // 2
情况2:如果 A 的 name 属性标记只读 writable: false ,并且是在严格模式下
'use strict' // 这句话要写在代码最顶部
let A = { name: 1 };
Object.defineProperty(A, 'name', {
writable: false,
enumerable: true,
configurable: true
})
let B = Object.create(A);
B.name = 2
console.log(A.name)
console.log(B.name)
// 直接抛出异常
// TypeError: Cannot assign to read only property 'name' of object '#<Object>'
如果是在非严格模式下是不会抛出异常的。A & B的 name 都为 1
情况3:如果 A 的属性有 get/set 方法了
let A = {
coun: 18,
get age() {
return this.coun
},
set age(o) {
this.coun = o
}
};
let B = Object.create(A);
B.age = 2
console.log(A.age) // 18
console.log(B.age) // 2
console.log(Object.keys(B)) // ['coun']
console.log(Object.keys(A)) // ['coun', 'age']
这里会直接调用 A 的 set 方法,并且 age 属性也不会添加到 B 对象上
我们可以使用 Object.defineProperty 来设置属性
let A = {
coun: 18,
get age() {
return this.coun
},
set age(o) {
this.coun = o
}
};
let B = Object.create(A);
Object.defineProperty(B, 'age', {
value: 2,
writable: true,
enumerable: true,
configurable: true
})
console.log(A.age)
console.log(B.age)
console.log(Object.keys(B)) // ['age']
console.log(Object.keys(A)) // ['coun', 'age']
for (v in B) {
console.log(v)
}
// age , coun
这样 B 对象就把 age 属性添加进去了,还可以避免出现情况2 & 情况3,所以如果是自己写 get/set方法那么在赋值的时候就需要注意了。
自己在写上面实例的时候遇到的问题o(╥﹏╥)o
let A = {
name: 2
}
Object.defineProperty(A, "name", {
get: function () {
return A.name;
},
set: function (val) {
A.name = val
},
enumerable: true
});
console.log(A.name)
// 直接死循环了
// RangeError: Maximum call stack size exceeded
-----
let A = {
name: 2
}
let para = 0
Object.defineProperty(A, "name", {
get: function () {
return para;
},
set: function (val) {
para = val
},
enumerable: true
});
console.log(A.name)
// 这样就对了,你都在重写 get/set 方法了,你还引用,相当于自己调用自己,不就死了么
Tip
Object.keys() 可以获取当前对象的属性,for in 遍历包含原型链上的属性
下一篇如何获取对象的属性...
还在更新...
网友评论