135 js 高程6.1

在JavaScript中最基本的创建一个对象的方法是new一个Object()的实例,然后再为其添加属性与方法,下例创建一个包含属性name的person对象,name属性的特征值为”xiaochang”:

?
1
2
3
4
5
6
<code class = "hljs javascript" >var person = new Object();
person.name = "xiaochang" ;
person.say = function(){
     console.log( "Hi, my name is " + this .name);
};
person.say();   //Hi, my name is xiaochang</code>

EAMAScript 5 定义了描述这些属性特征的各类特性,包括数据属性访问器属性
数据属性:该属性包含了一个数据值的位置,它包含了4个描述行为的特性:
1. [[Configurable]]:表示是否能通过delete删除属性从而重新定义属性,能否修改属性的特性,能否把属性修改为访问器属性。
2. [[Enumerable]]:表示能否用for-in循环返回。
3. [[writable]]:表示能否修改属性的值。
4. [[Value]]:包含这个属性的数据值。读取属性值的时候从这个位置读,写入属性值的时候更新到这个位置,默认值为undefined。

直接在对象上定义的属性的数据特性默认如下:
1. [[Configurable]]:true
2. [[Enumerable]]:true
3. [[writable]]:true
4. [[Value]]:”xiaochang” (初始时的赋值)

这些特性不能直接被访问,要修改属性的特性只能通过Object.defineProperty( )方法,该方法包含三个参数:属性所在的对象,属性的名字,描述符对象[configurable|enumerable|writable|value]。例如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<code class = "hljs cpp" >var person = {
     age: 100
};
 
Object.defineProperty(person, "name" ,{
     configurable: false ,
     writable: false ,
     value: "xiaochang"
});
 
Object.defineProperty(person, "tall" ,{
     value: 160
});
 
for (attr in person){
         console.log(attr); //name,age
}
console.log(person.name);   //xiaochang
person.name= "CC" ;           //为name属性指定新值
console.log(person.name);   //xiaochang
delete person.name;         //删除name属性
console.log(person.name);   //xiaochang
 
console.log(person.age);    //100
person.age= 200 ;             //为age属性指定新值
console.log(person.age);    //200
delete person.age;          //删除age属性
console.log(person.age);    //undefined
 
console.log(person.tall);   //160
person.tall = 160 ;          //修改tall属性的值
console.log(person.tall);   //160
delete person.tall;         //删除name属性
console.log(person.tall);   //160</code>

分析例子可知直接在对象上定义的属性,如age,[[Configurable]],[[Enumerable]],[[writable]]都被设置为true。
属性name的[[Configurable]],[[writable]]被设置为false,所以无法修改和删除。
调用Object.defineProperty( )方法时,如果不显示指定configurable,enumerable,writable的值,就默认为false,如属性tall。
另外需要注意的是当configurable设置为false后无法再将其改为true,且除了writable之外,无法修改其它特性。在configurable为true的情况下可多次调用Object.defineProperty( )修改同一属性。
在非严格情况下修改无法配置的属性操作会被忽略,在严格模式下会抛出错误。

访问器属性:包含getter和setter函数。读取访问器属性时,调用getter函数,返回有效的值;在写入访问器属性时,调用setter函数传入新值。它包含了4个特性:
1. [[Configurable]]:表示是否能通过delete删除属性从而重新定义属性,能否修改属性的特性,能否把属性修改为访问器属性。
2. [[Enumerable]]:表示能否用for-in循环返回。
3. [[Get]]:读取属性时调用的函数,默认undefined。
4. [[Set]]:写入属性时调用的函数,默认undefined。

getter和setter不一定要成对出现,只有getter函数证明该属性只读不可写,尝试写入在非严格模式下会被忽略,严格模式会抛出错误。相同,只有setter函数证明只写不能读,尝试读在非严格模式下返回undefined,严格模式则抛出错误。

访问器属性无法直接定义,必须使用Object.defineProperty( )来定义,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<code class = "hljs actionscript" >var person = {
     _name: "xiaochang" , //name属性只读不可写
     _age: 100 ,          //age属性只写不可读
     _tel: 123456      //tel属性可读可写
};
Object.defineProperty(person, "name" ,{
     get:function(){
         return this ._name;
     }
});
Object.defineProperty(person, "age" ,{
     set:function(newage){
         this ._age = newage;
     }
});
Object.defineProperty(person, "tel" ,{
     get:function(){
         return this ._tel;
     },
     set:function(newtel){
         this ._tel= newtel;
     }
});
console.log(person.name);   //"xiaochang"
person.name = "CC" ;         //尝试修改name属性
console.log(person.name);   //"xiaochang"
console.log(person.age);    //不可读属性,undefined
person.age = 200 ;           //修改age
console.log(person._age);   //直接读取对象方法才能访问的属性,可以看到值已更新200
console.log(person.tel);    //123456
person.age = 654321 ;        //更新tel
console.log(person.tel);    //654321</code>

属性前面的下划线表示只能通过对象方法访问的属性,当我们调用person.name时实际调用了name属性的getter函数(直接调用person._name可得到相同的结果,这样做访问器就没什么意义了)。通过上面例子中可以很清晰的看出属性与访问器之间的关系。

支持Object.defineProperty( )方法的浏览器有IE9+(IE8是第一实现Object.defineProperty( )方法的浏览器,但仅限于DOM对象,且只能创建访问器属性)、Firefox4+、Safari5+,Opera12+、Chrome。在不支持Object.defineProperty( )方法的浏览器中不能修改[[Configurable]],[[Enumerable]]。

在Object.defineProperty( )方法之前,要创建访问器属性,一般使用非标准的方法:__defineGetter__() 和__defineSetter__(),这两个方法最初在Firefox引入,后来chrome1和Opera9.5也支持。改写上面的tel属性访问器如下:

?
1
2
3
4
5
6
<code class = "hljs javascript" >person.__defineGetter__( "tel" ,function(){
     return this ._tel;
});
person.__defineSetter__( "tel" ,function(newtel){
     this ._tel = newtel;
});</code>

ECMAScript 5还定义Object.defineProperties( )方法,该方法包含两个参数:属性所在的对象,多个属性的名字和其描述符对象组成的对象。其作用于Object.defineProperty( )相同,区别是可一次性定于多个属性。支持该方法的浏览器有IE9+、Firefox4+、Safari5+,Opera12+、Chrome。上面的例子可以改写如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<code class = "hljs actionscript" >var person = {
     _name: "xiaochang" , //name属性只读不可写
     _age: 100 ,          //age属性只写不可读
     _tel: 123456      //tel属性可读可写
};
Object.defineProperties(person,{
     name:{
         get:function(){
             return this ._name;
         }
     },
     age:{
         set:function(newage){
             this ._age = newage;
         }
     },
     tel:{
         get:function(){
             return this ._tel;
         },
         set:function(newtel){
             this ._tel= newtel;
         }
     }
});</code>

对于上述讲到的属性特性,ECMAScript 5 给出了可以取得给定属性的描述符的方法Object.getOwnPropertyDescriptor(),该方法包含两个参数:属性所在的对象,要读取其描述符的属性名称。方法返回一个对象。如针对上面的例子可得:

?
1
2
3
4
5
6
7
8
9
10
<code class = "hljs actionscript" >var descriptor = Object.getOwnPropertyDescriptor(person, "tel" );
for (attr in descriptor ){
     console.log(attr+ ":" +descriptor[attr]);
}
 
运行结果如下:
get:function (){ return this ._tel;}
set:function (newtel){ this ._tel= newtel;}
enumerable: false
configurable: false </code>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值