JS中有两种属性值:数据属性 和 访问器属性
一、数据属性
它包含着一个数据值的位置,在这可以对数据值进行读写
数据属性包含四个特性:
- configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,默认值:true。
- enumerable:表示是否可以通过for-in循环返回属性,默认值:true。
- writable:表示能否修改属性的值,默认值:true。
- Value:包含这个属性的值,默认值:undefined。
1.1 writable
var person = {};
Object.defineProperty(person,'name',{
value: 'zhangsan'
})
person.name = 'Lisi';
console.log(person.name); //zhangsan
//发现value不能更改 因为defineProperty直接创建的属性writable默认为false,value值不可修改。
//修改writable为true
var person1 = {};
Object.defineProperty(person1,'name',{
writable:true,
value: 'zhangsan'
})
person1.name = 'Lisi';
console.log(person1.name); //Lisi
//发现value可以被修改
使用Object.defineProperty直接创建的属性writable默认为false,value值不可以被修改。在这个时候如果修改name的值为Lisi,在非严格模式下是不会报错,仅仅是忽略该操作,但是在严格模式下就会报错。
修改数据属性的默认特性要用到一个方法:Object.defineProperty()方法,这个方法有三个参数:属性所在的对象,属性名,一个描述符对象。
1.2 Configurable
var person = {
name: 'zhangsan',
age: 20,
sayName: function() {
console.log(this.name);
}
}
Object.defineProperty(person,"name",{
configurable: false
})
delete person.name; //操作被忽略,无法通过delete删除属性
Object.defineProperty(person,"name",{ //error
configurable: true
})
Object.defineProperty(person, "name",{ //error
enumerable:false //enumerable默认值是true
})
//从上面可以看出属性的值是不能被改变的
Object.defineProperty(person,'name',{
value: "wangwu"
})
console.log(person.name); //wangwu
//由于writable为true,所以可以修改value
Object.defineProperty(person,"name",{
writable: false //// writable可进行true -> false的单向修改
})
Object.defineProperty(person,'name',{ //error
value: "zhaoliu" //writable已经被修改为false,故value不能被修改
})
Object.defineProperty(person,'name',{ //error
writable: true //此时writable不能被修改false->true
})
从上面可以看出
当configurable设置为false时
- 不可以通过delete去掉该属性来重新定义属性
- 不可以转换为访问器属性
- configurable和enumerable不可以被修改
- writable可以单向修改true-->false,但不可以修改false-->true。
5.value的值能否被修改由writable来定,writable为true时value可以被修改,writable为false时value不能被修改。
注意:当configurable为false时,用delete删除属性,在非严格模式下只是忽略该操作,但不会报错,在严格模式下就会报错。其他不可被修改的操作无论是否在严格模式下都会报错。
1.3 Enumerable
enumerable表示对象属性是否可以在for...in和Object.keys()中被枚举。
var person = {}
Object.defineProperty(person,"num1",{
value: 1 //enumerable defaults to false
})
Object.defineProperty(person,"num2",{
value: 2,
enumerable: false
})
Object.defineProperty(person,"num3",{
value: 3,
enumerable: true
})
person.num4 = 4; //如果使用直接赋值的方式创建对象的属性,则这个属性的enumerable的默认值是 true
for(var num in person) {
console.log(num);
}
//num3 num4
通过上面可以看出只有在enumerable为true 的时候餐才能通过for-in返回属性的值。
2.访问器属性
这个属性不包含数据值,包含的是一对get和set方法,在读写访问器属性时,就是通过这两个方法来处理的。
访问器属性包含四个属性
- configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或能否把属性修改为访问器属性,默认为false
- enumerable:表示能否通过for-in循环返回属性,默认为false
- get:在读取属性时调用的函数,默认值为undefined
- set:在写入属性时调用的函数,默认值为undefined
var book = {
_year: 2020, //下划线表示内部属性,只能通过对象的方法来读写
editor: 2
}
console.log(book);
注意:访问器属性不能直接定义,要通过Object.defineProperty()这个方法来定义。
ECMAScript5中可以用Object.getOwnPropertyDescriptor()查看属性的特性。该方法接收两个参数:属性所在的对象名称和要读取特性的属性名称。
//通过Object.defineProperty()创建一个year属性
Object.defineProperty(book,'year',{
get() {
return this._year;
},
//若指定get不指定set,那就默认该属性是只读的
set(newYear) {
if(newYear !== this._year) {
this._year = newYear;
this.editor ++;
}
}
})
console.log(Object.getOwnPropertyDescriptor(book,"year"));
console.log("未修改:" + book.year);
book.year = 2020;
console.log('修改后year的值:' + book.year);
console.log('修改year的之后,editor属性的值:' + book.editor);
补充
1. Object.defineProperty()
通过object.defineProperty()可以直接修改对象上创建一个属性,也可以修改已有的属性。
这个方法有三个参数:
Object.defineProperty(obj, prop, descriptor)
属性所在的对象,属性名,一个描述符对象。
描述符对象包含六个属性:configurable、enumerable、writable、value、get、set ,要修改这些属性的特性,必须使用Object.defineProperty()方法。其他自定义的属性可以直接通过
【对象名】.【属性】 = 【修改的值】
来修改。
例如:person.name = "Lisi";
通过直接赋值的方式创建对象属性,其布尔值默认值是true,如果想通过Object.defineProperty来修改属性的特性时,只设置需要修改的特性值就可以了。
但是通过Object.defineProperty来创建的对象属性,其布尔值的默认值是false。
2.Object.defineProperties()
通过Object.defineProperties可以一次性对对象定义 多个属性。
var person = {};
Object.defineProperties(person, {
name: {
value: '小K哥',
writable: true
},
_age: {
value: 23,
enumerable: true,
writable: true,
configurable: true
},
age: {
get: function() {
return this._age;
},
set: function(value) {
this._age = value;
}
}
});