理解javascript中的对象属性

在前面已经有稍微介绍过【 javascript引用类型之object类型 】,今天就具体的说说什么是对象。

在javascript中,对象就是一组无序的名/值对的集合。并且,对象的操作,是对其引用的操作。即,将一个对象赋给一个变量x,实际上也只是将该对象的引用赋给x;倘若又将变量x赋给另一个变量y,那么也只是将y指向x所指向的那个对象。

在【 javascript引用类型之object类型 】中有介绍过创建Object类型实例的方法。对象实例都拥有属性和方法。其实从某种意义上来说,方法也是属性,只不过他的值是个函数。


属性类型

在javascript中,属性可以分为两种,一种是数据属性,另一种是访问器属性。

每个属性都又都包含一个名字和四个特性。

数据属性

对于数据属性而言,它包含了一个数据值的位置,它的值也是其特性之一。因此,它的四个特性分别为:

  • 可配置性(configurable):表示能否通过delete来删除属性,能否修改属性的特性,能否将其修改为访问器属性。若能,则值为true;若不能,则值为false。默认情况下,为true。
  • 可枚举性(enumerable):表示能否通过for/in循环来返回属性。若能,则为true;若不能,则为false。默认情况下为true。
  • 可写性(writable):表示能否修改属性的值。若能,则为true;若不能,则为false。默认为true。
  • 值(value):表示这个属性包含的数据值。读取数据属性时,从这个位置读;写入属性值时,将新值保存在这个位置。

访问器属性

访问器属性不包含数据值。它包含一对getter和setter函数,但是这两个函数不是必须的。当程序查询存取器属性值时,javascript就调用getter()方法,返回属性存取表达式的值;当程序设置存取器属性的值时,javascript就调用setter()方法,将赋值表达式右侧的值当作参数传入setter()。

前面提到,getter()和setter()方法不是必须的。当它同时具有这两个方法时,它是可读/写的;当它只有getter()方法时,它是只读的;当它只有setter()方法时,它是只写的。

存取器属性也同样拥有四个特性,它们分别是:

  • 可配置性(configurable):同数据属性。
  • 可枚举性(enumerable):同数据属性。
  • get:在读取属性时调用的函数。默认值为undefined。
  • set:在写入属性时调用的函数。默认值为undefined。

定义属性

在ECMAscript5中,可以用Object.defineProperty()方法来修改属性默认的特性值。这个方法有三个参数:属性所在的对象,属性的名字和一个描述符对象。其中,描述符对象的属性必须是属性的特性名。

       //数据属性
       var o={};
       Object.defineProperty(o,"x",{value:1,writable:true,enumerable:false,configurable:true});
       alert(o.x);  //1
       o.x=2;
       alert(o.x);  //2
       alert(o.propertyIsEnumerable("x"));  //false
       delete o.x;
       alert(o.x);  //undefined

       Object.defineProperty(o,"y",{value:4,writable:false,enumerable:true,configurable:false});
       alert(o.y); //4
       o.y=44;
       alert(o.y); //4
       alert(o.propertyIsEnumerable("y")); //true
       delete o.y;
       alert(o.y); //4

       //访问器属性
       var book={__year:2004,edition:1};
       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;
       alert(book.edition); //2
注意:一旦把属性定义为不可配置的,就不能再将其设置为可配置的了。

定义多个属性

ECMAscript5还定义了一个Object.defineProperties()方法,用于定义多个属性。这个方法有两个参数:第一个参数是属性所在的对象,第二个参数是一个映射表:

       var o={};
       Object.defineProperties(o,{ "x":{value:1,writable:true,enumerable:false,configurable:true},
                                    "y":{value:4,writable:false,enumerable:true,configurable:false}
                                  });
       
       alert(o.x);  //1
       o.x=2;
       alert(o.x);  //2
       alert(o.propertyIsEnumerable("x"));  //false
       delete o.x;
       alert(o.x);  //undefined


       alert(o.y); //4
       o.y=44;
       alert(o.y); //4
       alert(o.propertyIsEnumerable("y")); //true
       delete o.y;
       alert(o.y); //4
在不支持前面提到的两个方法的浏览器中,将不能修改属性的可配置性和可枚举性。

读取属性的特性

在ECMAscript5中,Object.getOwnPropertyDescriptor()方法可以取得给定属性的描述符。返回的是一个对象,如果是访问器属性,该对象的属性有:configurable、enumerable、get和set;如果是数据属性,该对象的属性有:configurable、enumerable、writable和value。

var o={x:1};
alert(Object.getOwnPropertyDescriptor(o,"x").value);  //1
alert(Object.getOwnPropertyDescriptor(o,"x").writable);  //true
alert(Object.getOwnPropertyDescriptor(o,"x").enumerable);  //true
alert(Object.getOwnPropertyDescriptor(o,"x").configurable);  //true

这个方法对于继承或者不存在的属性都将返回undefined:

var o={x:1};
alert(Object.getOwnPropertyDescriptor(o,"y"));  //undefined
alert(Object.getOwnPropertyDescriptor(o,"toString")); //undefined

属性查询和设置

其实前面也有提到过了,可以通过.或者[]来访问对象的属性:

var o1={x:1,y:2};
alert(o1.x);  //1
alert(o1["y"]); //2
注意,当以[]来访问属性时,[]内必须以字符串的形式出现。

也可以通过.和[]来设置属性的值:

var o={};
o.x=1;
o["y"]=2;

alert(o.x);  //1
alert(o.y);  //2
用[]来访问属性时,看起来像是数组。其实,由此也可以看出,javascript中的对象都是关联数组。

删除属性

在javascript中,用delete可以删除对象的属性,并且只能删除对象的自有属性或可配置性为true的属性。至于什么是可配置型,下面会提到。

var o={x:1,y:2};
alert(o.x); //1
delete o.x;
alert(o.x); //undefined
delete运算符只是断开属性与其宿主对象的关系,并不会去操作属性中的属性:

var p={z:1};
var o={x:1,y:p};
alert(o.y); //[object Object]
alert(p.z); //1
delete o.y;
alert(o.y); //undefined
alert(p.z); //1

检测属性

in运算符、hasOwnProperty()和propertyIsEnumerable()方法都可以用来检测属性,不过各自的检测机制不同。

in运算符

in运算符用来检查对象是否包含属性,如果有,不管是自有属性还是继承属性,都将返回true。

var o={x:1,y:2};
alert("x" in o);  //true
alert("z" in o);  //false
alert("toString" in o);  //true

hasOwnProperty()

hasOwnProperty()方法用来检测属性是否是自有属性,如果是,返回true;如果不是,则返回false。

var o={x:1,y:2};
alert(o.hasOwnProperty("x"));  //true
alert(o.hasOwnProperty("toString"));  //false

propertyIsEnumerable()

propertyIsEnumerable()方法用于检测属性是否是可枚举的。默认情况下,自有属性都是可枚举的,而内置属性则是不可枚举的。

var o={x:1,y:2};
alert(o.propertyIsEnumerable("x"));  //true
alert(o.propertyIsEnumerable("toString")); //false

枚举属性

用for/in循环可遍历对象中所有的可枚举属性。前面有提到过,默认情况下,自有属性是可枚举的,内置属性是不可枚举的。但是,属性有个特性可以改变属性的可枚举性(下面会提到)。那么,假如只想获得可枚举的自有属性,并且不包括方法,应该怎么操作呢?

可结合前面提到过的方法来过滤掉一些我们不想得到的属性:

过滤继承属性:
for(p in o){
   if(!o.hasOwnProperty(p)) continue;  
}

过滤方法:
for(p in o){
   if(typeOf o[p]==="function") continue;
}
注意,这边属性是通过[]来访问的,因为我们不知道对象拥有那些属性。这正是用[]来访问属性的重要用途。

在ECMAscript5中,还提供了一种方法来获得对象上所有的可枚举的实例属性。该方法接收一个对象作为参数,返回一个包含该对象中所有可枚举属性的字符串数组。

var o={x:1,y:2};
alert(Object.keys(o)); //x,y




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值