属性的特性:
writable: true // 可写 是否可设置该属性的值
enumerable: true // 可枚举 for/in是否可以获得该值
configurable: true // 是否可以删除属性或修改该属性的特性
// 在node中即使是false也会被删除
自定义属性的特性:
Object.defineProperty(对象, 属性名, 特性描述对象)
Object.defineProperties(对象, 多属性特性描述对象)
查看属性的特性:
Object.getOwnPropertyDescriptor(对象, 属性名) -> 私有属性的特性描述
小技巧:
好用的set get
自定义属性的特性
Object.defineProperty(对象, 属性名, 特性描述对象)
writable:false
var obj = {
x: 1,
y:2
}
Object.defineProperty(obj, "z", {
value: 3, // 值
writable: false, // 不可写
enumerable: true, // 可枚举
configurable: true, // 可删除和再次配置
})
obj.z = 4; // 写入失败
console.log(obj)

enumerable: false
在浏览器中打印obj可以显示,只是在for/in循环中不可枚举
在node中打印obj不可以显示
var obj = {
x: 1,
y:2
}
Object.defineProperty(obj, "z", {
value: 3,
writable: true,
enumerable: false, // 不可枚举
configurable: true,
})
console.log(obj)
for(var i in obj) {
console.log(i+" : "+obj[i])
}


configurable: false
- 在浏览器中delete obj.z 会返回false,不被删除。在node中会被删除
var obj = {
x: 1,
y:2
}
Object.defineProperty(obj, "z", {
value: 3,
writable: true,
enumerable: true,
configurable: false,
})


2. 不可重新写属性的特性配置,不然会报错。如果是true则不报错
var obj = {
x: 1,
y:2
}
Object.defineProperty(obj, "z", {
value: 3,
writable: true,
enumerable: true,
configurable: false, // 可删除和再次配置
})
Object.defineProperty(obj, "z", {
value: "z特性重新被配置",
writable: false,
enumerable: true,
configurable: true,
})
console.log(obj)

报错。
改成configurable: true
var obj = {
x: 1,
y:2
}
Object.defineProperty(obj, "z", {
value: 3, // 值
writable: true, // 不可写
enumerable: true, // 可枚举
configurable: true, // 可删除和再次配置
})
Object.defineProperty(obj, "z", {
value: "z特性重新被配置", // 值
writable: false, // 不可写
enumerable: true, // 不可枚举
configurable: true, // 不可删除 在node中不可行
})
console.log(obj)

重新配置成功
Object.defineProperties(对象, 多属性特性描述对象)
var obj = {
x: 1,
y:2
}
Object.defineProperties(obj, {
z: {
value: 3,
writable: true,
enumerable: true,
configurable: true,
},
t: {
value: 4,
writable: true,
enumerable: true,
configurable: true,
},
w: {
value: 5,
writable: true,
enumerable: true,
configurable: true,
},
})
console.log(obj)

查看属性的特性:
Object.getOwnPropertyDescriptor(对象, 属性名)
var obj = {
x: 1,
y:2
}
Object.defineProperty(obj, "z", {
value: 3,
writable: true,
enumerable: true,
configurable: true,
})
Object.defineProperty(obj, "z", {
value: "z特性重新被配置",
writable: false,
enumerable: true,
configurable: true,
})
console.log(Object.getOwnPropertyDescriptor(obj, 'z'))

小技巧的使用:
假设一个班上有男生10人,女生8人,每人班费10元,班上的人数不会变,但是费用会变动。
对象中的函数
let class0 = {
boy: 10,
girl: 8,
allmoney: 10 * 10 + 10 *8,
// 如果想要得到一个这样的对象
}
// 对象中的函数
let class1 = {
boy: 10,
girl: 8,
allmoney: 0
}
Object.defineProperty(class1, "onemoeny", {
set: function(money) {
this.allmoney = money * (this.boy + this.girl);
},
get: function() {
return "总共: " + this.allmoney;
},
})

只要修改了自定义属性中的onemoeny价格,再次查看对象,对象中的allmoney就会改变。

get是函数返回出来的结果。
注意的点:
自定义的属性不能在再配置set/get函数中出现,不然会死循环报错
let class1 = {
boy: 10,
girl: 8,
allmoney: 0
}
Object.defineProperty(class1, "onemoeny", {
set: function(money) {
this.onemoeny = 10; // 试试出现在set中不该出现的onemoney属性 重新调用该函数
this.allmoney = money * (this.boy + this.girl);
},
get: function() {
return "总共: " + this.allmoney;
},
})

最大次数超过堆栈的最大值
模拟死循环
let class1 = {
boy: 10,
girl: 8,
allmoney: 0,
num: 0,
}
Object.defineProperty(class1, "onemoeny", {
set: function(money) {
console.log("set num: " + this.num++)
this.onemoeny = 10; // 重新调用该函数
this.allmoney = money * (this.boy + this.girl);
},
get: function() {
return "总共: " + this.allmoney;
},
})
