JavaScript 数据属性和访问器属性
在JavaScript中对象被定义为"无序属性的集合,其属性可以包含基本值、对象或函数。"通俗点讲,我们可以把对象理解为一组一组的名值对,其中值可以是数据或函数。
创建自定义对象通常有两种方法,第一种就是创建一个Object的实例,然后再为其添加属性和方法,例如:
var person = new Object();
person.name = "Scott";
person.age = 24;
person.sayName = function(){
alert(person.name);
}
第二种方法即对象字面量法,一般推荐使用这种方法创建对象,例如:
var person = {
name: "Scott",
age: 24,
sayName: function(){
alert(this.name);
}
}
属性类型
JavaScript中定义了两种不同的属性:数据属性和访问器属性。数据属性一般用于存储数据数值,而访问器属性一般进行get/set操作,不能直接存储数据数值。在ES5中,我们为了描述属性(property)的各种特征,定义了特性(attribute)。在JavaScript中不能直接访问特性,我们把它放在两对方括号中,例如[[Enumerable]]。
- 数据属性
数据属性主要有四个特性描述其行为:
- [[Configurable]]:默认为true。表示能否通过delete删除属性从而重新定义属性,能否修改属性特性,或者能否把属性修改为访问器属性;
- [[Enumerable]]:默认为true。表示能否通过for-in循环返回属性;
- [[Writable]]:默认为true。表示能否修改属性的值。
- [[Value]]:默认值为undefined。表示包含属性的数据值。读写属性值都从这个位置进行。
对于上面直接在person对象上定义的属性,它们的[[Configurable]]、[[Enumerable]]、[[Writable]]特性都被默认设置为true,而[[Value]]特性被设置为特定值。如果想要修改属性默认的特性,可以使用ES5提供的Object.defineProperty()方法,这个方法接收三个参数:属性所在对象、属性的名字和一个描述符对象。描述符对象只能包含上述四个特性的一个或多个。例子如下:
var person = {
name: "Scott"
}
Object.defineProperty(person,"name",{
writable:false;
})
console.log(person.name); //"Scott"
person.name = "Evan";
console.log(person.name); //"Scott"
将person对象name属性的特性writable设置为false,此属性的值为不可修改的,因此对该属性的复制操作会直接忽略。
var person = {
name: "Scott"
}
Object.defineProperty(person,"name",{
configurable:false;
})
console.log(person.name); //"Scott"
delete person.name;
console.log(person.name); //"Scott"
可以看到,当把name属性的特性值configurable设置为false之后,就表示不能从对象中删除属性。但需要注意的是,当把属性定义为不可配置之后,就不能把它变回可配置的了。此时修改除writable之外的其它特性都会报错,例如:
var person = {
name: "Scott"
}
Object.defineProperty(person,"name",{
configurable:false;
})
Object.defineProperty(person,"name",{
configurable:true; //此处会抛出错误
})
也就是说,在把configurable特性修改为false之后,再修改其它特性就会有限制存在。
- 访问器属性
访问器属性不包含数据值。它包含一对getter和setter函数。当读取访问器属性时,会调用getter函数并返回有效值;当写入访问器属性时,会调用setter函数并传入新值,setter函数负责处理数据。该属性有四个特性:
- [[Configurable]]:默认为true。表示能否通过delete删除属性从而重新定义属性,能否修改属性特性,或者能否把属性修改为访问器属性;
- [[Enumerable]]:默认为true。表示能否通过for-in循环返回属性;
- [[Get]]:读取属性时调用的函数,默认为undefined;
- [[Set]]:写入属性时调用的函数,默认为undefined。
访问器属性不能直接定义,必须通过Object.defineProperty()函数定义,例如:
var person = {
_name: "Scott",
_age: 24,
_tel: 86247
};
//name属性为只读的
Object.defineProperty(person,"name",{
get: function(){
return this._name;
}
});
//age属性为只写不可读的
Object.defineProperty(person,"age",{
set: function(p){
this._age = p;
}
});
//tel属性为可读可写的
Object.defineProperty(person,"tel",{
get:function(){
return this._tel;
},
set: function(p){
this._tel = p;
}
});
console.log(person.name); //"Scott"
person.name = "Evan";
console.log(person.name); //"Scott",对name属性的修改无效
console.log(person.age); //undefined,不可读属性
person.age = 25;
console.log(person._age); //25,已经修改
console.log(person.tel); //"86247",可读属性
person.tel = "13975";
console.log(person.tel); //"13975",可以修改
属性前面的下划线表示只能通过对象方法访问的属性。当我们使用person.name时实际上调用的是name属性的getter函数,为person.name赋值时调用的是name属性的setter函数,这样属性和访问器之间的关系就很清晰了。
定义多个属性
实际上ES5为我们提供了为一个对象定义多个属性的方法,即Object.defineProperties(),该函数接收两个参数,属性所在的对象以及需要修改的属性及其描述符对象组成的对象,例如把上边的例子修改为一次性定义多个属性,如下:
var person = {
_name: "Scott",
_age: 24,
_tel: 86247
};
Object.defineProperties(person,{
name:{
get: function(){
return this._name;
}
},
age:{
set: function(p){
this._age = p;
}
},
tel:{
get:function(){
return this._tel;
},
set: function(p){
this._tel = p;
}
}
});
读取属性的特性
ES5提供了Object.getOwnPropertyDescripter()方法来获取给定属性的描述符。该方法接收两个参数:属性所在的对象和要读取其描述符的属性名称。结果会返回一个对象,如果是访问器属性,返回的对象有configuable、enumerable、get和set;如果是数据属性,这个返回对象的属性包括configuable、enumerable、writable和value。对于上面的例如,使用如下:
var person = {
_name: "Scott",
_age: 24,
_tel: 86247
};
Object.defineProperties(person,{
name:{
get: function(){
return this._name;
}
},
age:{
set: function(p){
this._age = p;
}
},
tel:{
get:function(){
return this._tel;
},
set: function(p){
this._tel = p;
}
}
});
var descripter = Object.getOwnPropertyDescripter(person,"tel");
console.log(descripter.value); //undefined
console.log(descripter.enumerable); //false
console.log(typeof descripter.get); //"function"
上面的代码中获取了person对象的tel属性,由于其是一个访问器属性,所以其value为undefined,enumerable为false,而get为指向getter函数的一个指针。
JavaScript 数据属性和访问器属性的更多相关文章
- JavaScript数据属性与访问器属性
ES5中对象的属性可以分为‘数据属性’和‘访问器属性’两种. 数据属性一般用于存储数据数值,访问器属性对应的是set/get操作,不能直接存储数据值. 数据属性特性:value.writable.en ...
- 浅谈Javascript数据属性与访问器属性
ES5中对象的属性可以分为‘数据属性’和‘访问器属性’两种. 数据属性一般用于存储数据数值,访问器属性对应的是set/get操作,不能直接存储数据值. 数据属性特性:value.writable.en ...
- JavaScript | 数据属性与访问器属性
属性类型 数据属性 - 包含一个数据值的位置,可以读取和写入值 [writable] 是否能修改属性的值 true [enumerable] 是否通过for in 循环返回属性(是否可以被枚举) tr ...
- javascript数据属性和访问器属性
var book={ _year:2004, edition:1};Object.defineProperty(book,"year",{ get:function(){ retu ...
- JavaScript 属性类型(数据属性和访问器属性)
数据属性 数据属性包含一个数据值的位置.在这个位置可以读取和写入值.数据属性有 4 个描述其行为的特性. [[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修 ...
- javascript对象属性——数据属性和访问器属性
ECMA-262第五版在定义时,描述了属性property的各种特征,定义这些特性是为了实现javascript引擎用的,为了表示该特性是内部值,规范把它们放在了两对儿方括号中,例如[[Enumera ...
- JavaScript中的数据属性和访问器属性
在学习JavaScript原型(prototype)和原型链(prototype chain)知识的时候,发现数据属性和访问器属性的重要性,通过不断的查找相关知识,浅显理解如下,若有差错,希望不吝赐教 ...
- Js中的数据属性和访问器属性
Js中的数据属性和访问器属性 在javaScript中,对象的属性分为两种类型:数据属性和访问器属性. 一.数据属性 1.数据属性:它包含的是一个数据值的位置,在这可以对数据值进行读写. 2.数据属性 ...
- js中属性类型:数据属性与访问器属性
js中属性类型分为两种:数据属性和访问器属性 在js中,对象都是由名值对构成的,名:就是我们所说的属性名,值就是属性对应的值(基本值.对象.方法). ECMA-262第5版定义了只有内部才用的特性,描 ...
随机推荐
- 数据分布转换:非正态 -> 正态
来源:丁香园论坛:SPSS上的把非正态分布数据转换为正态分布数据 一楼 可以应用变量变换的方法,将不服从正态分布的资料转化为非正态分布或近似正态分布.常用的变量变换方法有对数变换.平方根变换.倒数变换 ...
- LeetCode All in One 题目讲解汇总(持续更新中...)
终于将LeetCode的免费题刷完了,真是漫长的第一遍啊,估计很多题都忘的差不多了,这次开个题目汇总贴,并附上每道题目的解题连接,方便之后查阅吧~ 477 Total Hamming Distance ...
- Xamarin.Android-捕获未处理异常(全局异常)
一.前言 android中如果出现了未处理的异常,程序会闪退,这是非常不好的用户体验,很多用户会因此卸载APP,因此未处理的异常是应该尽力避免的. 有些很难避免的异常(如:IO.网络等),应在代码中进 ...
- Lesson 16 A polite request
Text If you park your car in the wrong place, a traffic policeman will soon find it. You will be ver ...
- Lesson 15 Good news
Text The secretary told me that Mr. Harmsworth would see me. I felt very nervous when I went into hi ...
- Angular2学习笔记——NgModule
在Angular2中一个Module指的是使用@NgModule修饰的class.@NgModule利用一个元数据对象来告诉Angular如何去编译和运行代码.一个模块内部可以包含组件.指令.管道,并 ...
- [免费了] SailingEase .NET Resources Tool (.NET 多语言资源编辑器)
这是我2010年左右,写 Winform IDE (http://www.cnblogs.com/sheng_chao/p/4387249.html)项目时延伸出的一个小项目. 最初是以共享软件的形式 ...
- Markdown是怎样接管我的各种的写作工作的
对于一个程序猿来说,没有什么比单纯的写代码更能让人兴奋了.如果能让你像写代码一样写文档,不用再面对那些繁琐的样式,你会怎么看?它就是Markdown!即使博客园已经有不少介绍的文章了,但是我依然还是不 ...
- UniversalImageLoader的一个小问题
最近在使用UniversalImageLoader时遇到了一个小问题,多个地方同时通过ImageLoader.getInstance().loadImage(url, new ImageSize(dp ...
- Lamda表达式多个字段排序问题 ThenBy、ThenByDescending
示例代码: //ThenBy - 在 OrderBy 或 OrderByDescending 的基础上再正序排序 //ThenByDescending - 在 OrderBy 或 OrderByDes ...