JavaScript對象和屬性分析

JavaScript對象和屬性分析,面向對象(Object-Oriented,OO)的語言有一個標志,那就是它們都有類的概念,而通過類可以創建任意多個具有相同屬性和方法的對象。ECMA-262把對象定義為:“無序屬性的集合,其屬性可以包含基本值、對象或者函數。”嚴格來講,這就相當於說對象是一組沒有特定順序的值,對象的每個屬性或方法都有一個名字,而每個名字都映射到一個值。

一、理解對象

創建自定義對象的最簡單方式就是創建一個object的實例,然後再為它添加屬性和方法,如下所示:

[javascript]view plaincopy

varperson=newObject();

person.name='MyName';

person.age=18;

person.getName=function(){

returnthis.name;

}

早期的JavaScript開發人員經常使用這個模式創建新對象,幾年後,對象字面量成為創建這種對象的首選模式。(比較清楚的查找對象包含的屬性及方法)

[javascript]view plaincopy

varperson={

name:'Myname',

age:18,

getName:function(){

returnthis.name;

}

}[javascript]view plaincopy

varobj=Object.create({x:1});

obj.x//1

typeofobj.toString//"function"

obj.hasOwnProperty('x');//false

varobj=Object.create(null);

obj.toString//undefined[javascript]view plaincopy

varperson={age:28,title:'fe'};

deleteperson.age;//true

deleteperson['title'];//true

person.age;//undefined

deleteperson.age;//true

deleteObject.prototype;//false,

vardescriptor=Object.getOwnPropertyDescriptor(Object,'prototype');

descriptor.configurable;//false

//刪除全局變量

varglobalVal=1;

deleteglobalVal;//false

//刪除局部變量

(function(){

varlocalVal=1;

returndeletelocalVal;

}());//false

//刪除函數聲明

functionfd(){}

deletefd;//false

(function(){

functionfd(){};

returndeletefd;

}());//false

//刪除隱式全局變量

ohNo=1;

window.ohNo;//1

deleteohNo;//true 對象標簽和對象序列化:[javascript]view plaincopy

vartoString=Object.prototype.toString;

functiongetType(o){returntoString.call(o).slice(8,-1);};

toString.call(null);//"[objectNull]"

getType(null);//"Null"

getType(undefined);//"Undefined"

getType(1);//"Number"

getType(newNumber(1));//"Number"

typeofnewNumber(1);//"object"

getType(true);//"Boolean"

getType(newBoolean(true));//"Boolean" (2)、extensible標簽 [javascript]view plaincopy

varobj={x:1,y:2};

Object.isExtensible(obj);//true

Object.preventExtensions(obj);

Object.isExtensible(obj);//false

obj.z=1;

obj.z;//undefined,addnewpropertyfailed

Object.getOwnPropertyDescriptor(obj,'x');

//Object{value:1,writable:true,enumerable:true,configurable:true}

Object.seal(obj);

Object.getOwnPropertyDescriptor(obj,'x');

//Object{value:1,writable:true,enumerable:true,configurable:false}

Object.isSealed(obj);//true

Object.freeze(obj);

Object.getOwnPropertyDescriptor(obj,'x');

//Object{value:1,writable:false,enumerable:true,configurable:false}

Object.isFrozen(obj);//true

//[caution]notaffectsprototypechain!!! (3)、序列化 [javascript]view plaincopy

varobj={x:1,y:true,z:[1,2,3],nullVal:null};

JSON.stringify(obj);//"{"x":1,"y":true,"z":[1,2,3],"nullVal":null}"

obj={val:undefined,a:NaN,b:Infinity,c:newDate()};

JSON.stringify(obj);//"{"a":null,"b":null,"c":"2015-01-20T14:15:43.910Z"}"

obj=JSON.parse('{"x":1}');

obj.x;//1 (4)、自定義序列化 [javascript]view plaincopy

varobj={

x:1,

y:2,

o:{

o1:1,

o2:2,

toJSON:function(){

returnthis.o1+this.o2;

}

}

};

JSON.stringify(obj);//"{"x":1,"y":2,"o":3}"

二、屬性類型

ECMA-262第5版定義隻有內部采用的特性(attribute)時,描述瞭屬性(property)的各種特征。ECMA-262定義這些特性是為瞭實現JavaScript引擎用的,因此JavaScript中不能直接訪問它們。為瞭表示特性是內部值,該規范把它們放在瞭兩對兒方括號中,例如[[Enumerable]].

ECMAScript中有兩種屬性:數據屬性和訪問器屬性

1、數據屬性:

數據屬性指包含一個數據值的位置,可在該位置讀取或寫入值,該屬性有4個供述其行為的特性:

[[configurable]]:表示能否使用delete操作符刪除從而重新定義,或能否修改為訪問器屬性。默認為true;

[[Enumberable]]:表示是否可通過for-in循環返回屬性。默認true;

[[Writable]]:表示是否可修改屬性的值。默認true;

[[Value]]:包含該屬性的數據值。讀取/寫入都是該值。默認為undefined;如上面實例對象person中定義瞭name屬性,其值為’My name’,對該值的修改都反正在這個位置。

要修改對象屬性的默認特征(默認都為true),可調用Object.defineProperty()方法,它接收三個參數:屬性所在對象、屬性名和一個描述符對象(必須是:configurable、enumberable、writable和value,可設置一個或多個值)。可以修改對應的特性值。例如:瀏覽器支持:IE9+、Firefox 4+、Chrome、Safari5+)

[javascript]view plaincopy

varperson={};

Object.defineProperty(person,'name',{

configurable:false,

writable:false,

value:'Jack'

});

alert(person.name);//Jack

deleteperson.name;

person.name='lily';

alert(person.name);//Jack

可以看出,delete及重置person.name的值都沒有生效,這就是因為調用defineProperty函數修改瞭對象屬性的特征;值得註意的是一旦將configurable設置為false,則無法再使用defineProperty將其修改為true(執行會報錯:can't redefine non-configurable property);在調用Object.defineProperty()方法時,如果不指定,configurable、enumberable和writable特性默認值都是false。

2、訪問器屬性:

它主要包括一對getter和setter函數,在讀取訪問器屬性時,會調用getter返回有效值;寫入訪問器屬性時,調用setter,寫入新值;該屬性有以下4個特征:

[[Configurable]]:是否可通過delete操作符刪除重新定義屬性;

[[Numberable]]:是否可通過for-in循環查找該屬性;

[[Get]]:讀取屬性時調用,默認:undefined;

[[Set]]:寫入屬性時調用,默認:undefined;

訪問器屬性不能直接定義,必須使用defineProperty()來定義,如下:

[javascript]view plaincopy

varperson={

_age:18

};

Object.defineProperty(person,'isAdult',{

get:function(){

if(this._age>=18){

returntrue;

}else{

returnfalse;

}

}

});

alert(person.isAdult?'成年':'未成年');//成年[javascript]view plaincopy

Object.defineProperties(person,{

title:{value:'fe',enumerable:true},

corp:{value:'BABA',enumerable:true},

salary:{value:50000,enumerable:true,writable:true},

luck:{

get:function(){

returnMath.random()>0.5?'good':'bad';

}

},

promote:{

set:function(level){

this.salary*=1+level*0.1;

}

}

});

Object.getOwnPropertyDescriptor(person,'salary');

//Object{value:50000,writable:true,enumerable:true,configurable:false}

Object.getOwnPropertyDescriptor(person,'corp');

//Object{value:"BABA",writable:false,enumerable:true,configurable:false}

person.salary;//50000

person.promote=2;

使用Object.getOwnPropertyDescriptor()方法可以取得給定屬性的特性,這個方法接收兩個參數:屬性所在的對象和要讀取其描述的屬性名稱。返回值是一個對象,如果是訪問器屬性,這個對象的屬性有configurable,enumberable,

屬性getter/setter方法實例:

[javascript]view plaincopy

varman={

name:'Bosn',

weibo:'@Bosn',

getage(){

returnnewDate().getFullYear()-1988;

},

setage(val){

console.log('Agecan\'tbesetto'+val);

}

}

console.log(man.age);//27

man.age=100;//Agecan'tbesetto100

console.log(man.age);//still27

[javascript]view plaincopy

varman={

weibo:'@Bosn',

$age:null,

getage(){

if(this.$age==undefined){

returnnewDate().getFullYear()-1988;

}else{

returnthis.$age;

}

},

setage(val){

val=+val;

if(!isNaN(val)&&val>0&&val<150){

this.$age=+val;

}else{

thrownewError('Incorrectval='+val);

}

}

}

console.log(man.age);//27

man.age=100;

console.log(man.age);//100;

man.age='abc';//error:Incorrectval=NaN

[javascript]view plaincopy

functionfoo(){}

Object.defineProperty(foo.prototype,'z',{

get:function(){

return1;

}

});

varobj=newfoo();

obj.z;//1

obj.z=10;

obj.z;//still1

Object.defineProperty(obj,'z',{

value:100,configurable:true

}

);

obj.z;//100;

deleteobj.z;

obj.z;//backto1

varo={};

Object.defineProperty(o,'x',{value:1});//writable=false,configurable=false

varobj=Object.create(o);

obj.x;//1

obj.x=200;

obj.x;//still1,can'tchangeit

Object.defineProperty(obj,'x',{writable:true,configurable:true,value:100});

obj.x;//100

obj.x=500;

obj.x;//500[javascript]view plaincopy

vardescriptor=Object.getOwnPropertyDescriptor(person,'_age');

alert(descriptor.value);//19

alert(descriptor.configurable);//false

alert(typeofdescriptor.get);//undefined

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *