Javascript之【對象】的深刻理解

  對象函數

             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同樣的屬性,是個定義了用來修改其餘屬性的屬性,地位至關於後勤部長。

相關文章
相關標籤/搜索