對象函數
ECMA-262把對象定義爲:「無序屬性的集合,其屬性能夠包含基本值、對象或者函數。」性能
因而,咱們能夠將對象想象成散列表:就是一些名值對,其中值能夠是數據或函數this
1.理解對象及其內部機制spa
咱們先來建立一個最簡單的Object實例,同時爲它添加屬性和方法:code
1 var person=new Object();
2 person.name="Sleipnir"; 3 person.age=23; 4 person.job="Software Enginner"; 5 6 person.sayname=function(){ 7 alert(this.name); 8 };
有時候這種直接賦值的方式太繁瑣,咱們還能夠用對象字面量的方式來賦值:對象
1 var person={
2 name:"Sleipnir", 3 age:23, 4 job:"Software Enginner", 5 6 sayname:function(){ 7 alert(this.name); 8 } 9 };
這兩種建立對象的效果都是同樣的,下面,咱們來深刻對象內部,來探討屬性類型blog
2.屬性類型ip
ECMAScript有兩種屬性:數據屬性 和 訪問器屬性get
2.1數據屬性:它包含一個數據值的位置,在這個位置能夠讀取和寫入值,它有4個用來描述其行爲的特性:Configurable\Enumerable\Writable\Valueit
Configurable:表示可否經過delete來刪除從而從新定義屬性,它的默認值爲true;
Enumerable:表示屬性可否被使用for-in來遍歷,默認值爲true;
Writable:表示可否被修改,默認值爲true;
Value:包含屬性的數據值,默認值爲underfined
像在上面對象中直接定義的屬性,它們的configurable,enumerable,writable都默認是true,value就是設置的「Sleipnir」這個值
想查看特性的值,就須要用到Object.getOwnPropertyDescriptor()這個方法:
在上面的對象的基礎上,咱們來查看屬性的特性:
1 var aa=Object.getOwnPropertyDescriptor(person,"name"); 2 console.log(aa.configurable); //true 3 console.log(aa.enumerable); //true 4 console.log(aa.writable); //true 5 console.log(aa.value); //"Sleipnir"
要想修改默認的特性,就要用到Object.defineProperty()這個方法,概念不說太多,咱們直接來舉個栗子:
在上面的對象的基礎上,咱們來修改屬性的特性:
1 Object.defineProperty(person,"name",{ 2 writable:false, 3 enumerable:false, 4 value:"xiaoxiao", 5 configurable:false 6 }); 7 8 console.log(person.name); //"xiaoxiao" 9 person.name="love"; 10 console.log(person.name); //"xiaoxiao"
從上面的代碼能夠看出,當writable從默認的true被修改爲false後,你再給name賦值就沒法成功了,它仍是顯示默認的「xiaoxiao」
然而,有一點要注意,當把confugurable設置成false後,就沒辦法把屬性設置回可設置狀態了,換句話說,是不可逆的,當把confugurable設成false後,再用 Object.defineProperty()修改除writable以外的特性,都會致使錯誤
這裏有個坑,你直接在對象上定義的屬性,它的數據屬性值都默認是true,可是若是你是用Object.defineProperty()給對象建立的屬性,configurable、enumerable和writable特性的默認值都是false
固然了,一個一個屬性修改太麻煩了,因而還有個Object.defineProperties(),能同時修改多個屬性:
1 Object.defineProperties(person,{ 2 name: { 3 writable:true, 4 value:"long" 5 }, 6 age: { 7 writable:true, 8 value:25 9 }, 10 job: { 11 writable:true, 12 value:"gongren" 13 } 14 }); 15
2.2 訪問器屬性:跟數據屬性同樣,它也有4個特性:configurable,enumerable,get,set
前兩個特性不用贅述,後兩個get和set分別是讀取/寫入屬性時調用的函數,默認值都是underfined
訪問器屬性無法直接定義,必須使用Object.defineProperty()來定義,舉個栗子:
1 var book={ _year:2017, 2 edition:1 3 }; 4 Object.defineProperty(book,"year",{ 5 get: function(){ 6 return this._year; 7 }, 8 set: function(newValue){ 9 if(newValue>2017){ 10 this._year=newValue; 11 this.edition+=newValue-2017; 12 } 13 } 14 }); 15 16 book.year=2018; 17 console.log(book.edition); //2
這裏就是比較有意思的地方,咱們加入的屬性「year」,在加入時並無賦值,而是定義了get和set函數,用來處理在外部賦給year的值,咱們在外面賦值2018,而後給year定義的get和set函數就利用2018來修改_year和edition的值。這就是使用訪問器屬性的常見方式,即設置一個屬性的值會致使其餘屬性發生變化
看到這裏,可能有的同窗有個問題:不是說用Object.defineProperty()方法定義的屬性的特徵值包括writable都是false嗎?爲何「book.year=2018」還能生效呢?
其實緣由是,你用Object.getOwnPropertyDescriptor()取得特徵值查看會發現,它的writable顯示爲「underfined」,因此能夠這樣想,year並非和_year,edition同樣的屬性,是個定義了用來修改其餘屬性的屬性,地位至關於後勤部長。