对象的每个属性,额外有几个选项:
value:默认值
writable:是否可写
configurable:是否可以重新配置
enumerable:是否可遍历
get:getter,读取属性时触发, 对象.属性名 作用:计算属性
set:setter,为属性赋值时触发, 对象.属性名=值 作用:赋值检查
直接声明的属性:{属性名:值},其配置项默认都是true
用Object.defineProperty(…),新增属性所有配置默认都是false
get,set 属性与write enumerable:互斥,不能同时存在
Object.defineProperty(obj, "id", {
writable: false, //是否可写
configurable: false, //是否可重新配置
enumerable:false, //是否可遍历
})
1、精确添加对象属性
Object.defineProperty(参数1,参数2,参数3):
参数1:要修改的对象
参数2:要修改的属性名,必须是字符串格式
参数3:要修改的具体配置
例如新增一个id属性,默认值001:
Object.defineProperty(obj, "id", {value: 001,writable: false … })
新增属性,所有配置默认都是假
2、精确配置多个对象属性
Object.defineProperties(要修改的对象, {属性1:{writable:false… },属性2:{ }…. }}
var obj = {
id: 100,
}
//id不可修改,配置不可改
//新增name属性,默认值“刚刚”,不可修改,配置不可改
//新增salary,默认值9999,不可改,不可配置,不可遍历
Object.defineProperties(obj, {
//此方式添加的属性,所有的默认值都是true
id: {
writable: false,
configurable: false
},
//用此方式添加的新属性,所有的默认值都是false
name: {
value: "刚刚",
enumerable: true //要主动声明,才能遍历
},
salary: {
value: 9999,
}
});
console.log(obj);
for (var name in obj) {
console.log(name); //salary不可遍历,不可见
}
3、计算属性 getter
计算属性get 与value/writable配置项是互斥的
get 获取,当读取一个属性时,会自动触发get属性的函数,把此函数的返回值 作为属性的值
调用时:对象.方法,不需要写()
写法1: | 写法2(语法糖写法): |
Object.defineProperty(r1, "area", { get: function ( ) { return this.width * this.height; } }) | var r1 = { width: 100, height: 30, get area( ) { return this.width * this.height; }, } |
var r1 = {
width: 100,
height: 50,
//面积:特点:值是计算出来的
}
//声明计算属性:getter
Object.defineProperty(r1, "area", {
//计算属性get 与value/writable配置项是互斥的
//get 获取,当读取一个属性时,会自动触发get属性的函数,
//把此函数的返回值 作为属性的值
get: function () {
console.log("有人要读取面积!!");
return this.width * this.height;
}
})
console.log(r1.area);
//得到周长
Object.defineProperty(r1,"perimeter",{
get:function(){
console.log("周长");
return (this.width+this.height)*2;
}
})
console.log(r1.perimeter);
4、赋值监听 setter
赋值监听:防止一些明显错误的值的添加
做法:修改属性的set,在此方法中接收赋值,然后对值进行检查,如果正确才赋值,此处不能给当前属性赋值,会触发当前属性的set方法,导致无限循环,所以必须额外声明一个变量来存储值,读取时,再通过get方法,来返回存储的变量(额外声明的变量一般用前缀__)
写法1: | 写法2(语法糖写法): |
var __age; Object.defineProperty(yanan, "age", { set: function (value) { if (value >= 1 && value <= 100) { // this.age=value; 无限循环 __age = value; } else { throw Error("年龄范围错误" + value); } }, get: function () { return __age; } }) 这种会给window增加变量__age,可以将整体用一个匿名函数包裹起来 | var yanan = { name: "芳芳", set age(value) { if (value >= 1 && value <= 100) { this.__age = value; //自动创建 } else { throw Error("年龄范围错误"); } }, get age( ) { return this.__age; }, }; __age :应该是一个不可遍历的属性 |