js中属性类型:数据属性与访问器属性

js中属性类型分为两种:数据属性和访问器属性

在js中,对象都是由名值对构成的,名:就是我们所说的属性名,值就是属性对应的值(基本值、对象、方法)。

ECMA-262第5版定义了只有内部才用的特性,描述了属性的各种特征,比如,这个属性能否被删除、能否被枚举、能否被修改、以及读取属性的值。

这些特性是为了实现JavaScript引擎用的,因此在JavaScript中不能直接访问他们。

1、先来说一下数据属性

数据属性:包含一个数据值的位置。在这个位置可以读取和写入值。数据属性有4个描述其行为的特性。

Configurable:表示能否通过delete删除属性,从而重新定义属性,能否修改属性的特性,或则能否把属性修改为访问器属性。我们一般在对象上自定义的属性,它们的这个特性一般为true。

Enumberable:表示能否通过for-in循环返回属性(枚举),自定义的对象属性,默认值为true。

Writable:表示能否修改属性的值,自定义对象的属性,这个特性值默认为true。

Value:包含这个属性的数据值,读取属性值的时候从这个读,写入属性值的时候,把新值保存在这个位置。这个特性的默认值为undefined。

ECMAScript5定义了一个修改属性的这些默认特性的方法:Object.defineProperty();

这个方法接收三个参数:属性所在的对象、属性的名字(字符串形式)、一个描述符对象。其中描述符对象的属性必须是:configurable、enumberable、writable、value,设置其中的一个或多个值,可以修改对应的特性值。例如:

    var person={};
Object.defineProperty(person,"name",{
writable:false,
value:"Nicholas"
});
console.log(Object.getOwnPropertyDescriptor(person,"name"));//读取属性的特性的方法,后面会介绍
console.log(person.name);//Nicholas
person.name="Greg";
console.log(person.name);//Nicholas

上面,对name属性的两个特性writable、value进行了设置,可见,我们更改name属性的值是无效的,在严格模式下会报错;

当用Object.defineProperty()创建一个新属性时,若不指定configurable、enumberable、writable这些特性时,都是false,若果在原来设置过的基础上设置其中的一个或多个,则无此限制。

另外,当设置configurable为false后,也就是把该属性变成不可设置的,除delete不能删除该属性外,再次用Object.defineProperty()方法设置除writable特性外的其它特性时,在非严格模式时什么都不会发生,在严格模式时会报错。(同时configurable特性也设置不了true了!!!);

2、访问器属性:

访问器属性不包含数据值,他们包含一对儿getter和setter函数(不过,这两个函数都不是必须的)。在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值;在写入访问器属性时,会调用setter函数并传入新值,这个函数负责决定如何处理数据。访问器属性有如下4个特性。

configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或则能否把属性修改为数据属性。对于直接在对象上定义的属性,这个特性的默认值为true。

enumberable:表示能否通过for-in来循环返回属性。对于直接在对象上定义的属性,这个特性的默认值为true。

get:读取属性时调用的函数。默认值为undefined

set:在写入属性时调用的函数。默认值为undefined

访问器属性不能直接定义,必须使用Object.defineProperty()来定义。请看下面的例子:

    var book={
_year:2004,
edition:1
};
//下边给book对象设置一个year(访问器属性)
Object.defineProperty(book,"year",{
get:function(){
return this._year;
},
set:function(newValue){
if(newValue>2004){
this._year=newValue;
this.edition=newValue - 2004;
}
}
});
book.year =2005;
console.log(book.edition);//1
console.log(book._year);//2005
console.log(book.year);//2005
console.log(book);//{_year: 2005, edition: 1}

可见,创建的访问器属性,用console是打印不出来的,我们常见的使用访问器属性的方式就是上述这种方式,修改访问器属性,会导致其他属性变化!!!

当然,不一定非要指定get和set,只指定get就是只能读,不能写,只指定set就是不能读。

当然也可以同时定义多个属性,用:Object.defineProperties()方法,利用这个方法可以通过描述符一次定义多个属性,这个方法接收两个参数,第一个参数是要添加和修改其属性的对象,第二个参数(对象:描述符)的属性与第一个对象中要添加或修改的属性要一一对应。如:

    var book={};
Object.defineProperties(book,{
_year:{//定义一个数据属性,其它为指定的特性值为false
writable:true,
value:2004
},
edition:{//同样是一个数据属性
writable:true,
value:1
},
year:{
get:function(){
return this._year;
},
set:function(newValue){
if(newValue>2004){
this._year=newValue;
this.edition+=newValue-2004;
}
}
}
});
book.year=2003;
console.log(book);//{_year: 2004, edition: 1}
book.year=2005;
console.log(book);//{_year: 2005, edition: 1}
// Object.getOwnPropertyDescriptor();用来读取给定属性的描述符,这个方法有两个参数,属性所在的对象和要读取其描述符的属性名,返回一个对象。
var descriptor=Object.getOwnPropertyDescriptor(book,"_year");//数据属性
var descriptor2=Object.getOwnPropertyDescriptor(book,"year");//访问器属性
console.log(descriptor);//{value: 2005, writable: true, enumerable: false, configurable: false}
console.log(descriptor2);//{get: ƒ, set: ƒ, enumerable: false, configurable: false}
Object.getOwnPropertyDescriptor();用来读取给定属性的描述符,这个方法有两个参数,属性所在的对象和要读取其描述符的属性名,返回一个对象。这个方法可以在任何浏览器使用。
上一篇:Contest2162 - 2019-3-28 高一noip基础知识点 测试5 题解版


下一篇:codevs3304水果姐逛水果街