理解Object.defineProperty

Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或在修改一個對象的現有屬性,並返回這個對象(即第一個參數obj)vue

語法:函數

Object.defineProperty(obj , prop , descriptor)測試


//
obj:要在其上定義屬性的對象 //prop:要定義或修改的屬性的名稱 //descriptor:將被定義或修改的屬性描述符

 vue.js就是經過Object.defineProperty實現雙向綁定spa

 

給對象的屬性添加特性描述,目前提供兩種形式:數據描述和存取器描述雙向綁定

數據描述code

當修改或定義對象的某個屬性的時候,給這個屬性添加一些特性對象

value: 設置屬性的值
writable: 值是否能夠重寫。true | false
enumerable: 目標屬性是否能夠被枚舉。true | false
configurable: 目標屬性是否能夠被刪除或是否能夠再次修改特性 true | falseblog

 

value:屬性對應的值,能夠是任意類型的值,默認爲undefinedip

let obj = {}
//第一種狀況:不設置value屬性
Object.defineProperty(obj,"newKey",{

});
console.log( obj.newKey );  //undefined
------------------------------
//第二種狀況:設置value屬性
Object.defineProperty(obj,"newKey",{
    value:"hello"
});
console.log( obj.newKey );  //hello

 

writable:屬性的值是否能夠被重寫,默認爲false,設置爲true能夠被重寫ci

    let Person = {};
    Object.defineProperty(Person,'city',{
        city:'倫敦'
        //writable默認爲false,不能改變屬性值
    })
    Person.city = '巴黎';
    console.log(Person.city);//undefined
   let Person = {};
    Object.defineProperty(Person,'city',{
        city:'倫敦',
        writable:true
    })
    Person.city = '巴黎';
    console.log(Person.city);//巴黎

 

enumerable:此屬性是否能夠被枚舉

設置爲true能夠被枚舉;設置爲false,不能被枚舉(默認false)

var obj = {}
//第一種狀況:enumerable設置爲false,不能被枚舉。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false
});

//枚舉對象的屬性
for( var attr in obj ){
    console.log( attr );  
}
//第二種狀況:enumerable設置爲true,能夠被枚舉。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:true
});

//枚舉對象的屬性
for( var attr in obj ){
    console.log( attr );  //newKey
}

 

configurable:是否能夠刪除目標屬性或是否能夠再次修改屬性的特性

設置true能夠被刪除或能夠從新設置特性,false不能設置

這個屬性起到的做用

  1. 目標屬性是否能夠使用delete刪除

  2. 目標屬性是否能夠再次設置特性

//-----------------測試目標屬性是否能被刪除------------------------
var obj = {}
//第一種狀況:configurable設置爲false,不能被刪除。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:false
});
//刪除屬性
delete obj.newKey;
console.log( obj.newKey ); //hello

//第二種狀況:configurable設置爲true,能夠被刪除。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:true
});
//刪除屬性
delete obj.newKey;
console.log( obj.newKey ); //undefined
//-----------------測試是否能夠再次修改特性------------------------
var obj = {}
//第一種狀況:configurable設置爲false,不能再次修改特性。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:false
});

//從新修改特性
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true,
    enumerable:true,
    configurable:true
});
console.log( obj.newKey ); //報錯:Uncaught TypeError: Cannot redefine property: newKey

//第二種狀況:configurable設置爲true,能夠再次修改特性。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:true
});

//從新修改特性
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true,
    enumerable:true,
    configurable:true
});
console.log( obj.newKey ); //hello

一旦使用Object.defineProperty給對象添加屬性,那麼若是不設置屬性的特性,那麼configurable、enumerable、writable這些值都爲默認的false

 

存取器描述

當使用存取器描述屬性的特性的時候,容許設置如下特性屬性

當設置或獲取對象的某個屬性的值的時候,能夠提供getter/setter方法,沒有的話則爲undefined

  • getter 是一種得到屬性值的方法

  • setter是一種設置屬性值的方法

注意:當使用了getter或setter方法,不容許使用writable和value這兩個屬性

var obj = {};
var initValue = 'hello';
Object.defineProperty(obj,"newKey",{
    get:function (){
        //當獲取值的時候觸發的函數
        return initValue;    
    },
    set:function (value){
        //當設置值的時候觸發的函數,設置的新值經過參數value拿到
        initValue = value;
    }
});
//獲取值
console.log( obj.newKey );  //hello

//設置值
obj.newKey = 'change value';

console.log( obj.newKey ); //change value

get或set不是必須成對出現,任寫其一就能夠。若是不設置方法,則get和set的默認值爲undefined

      let obj = {
          num:4
      };
       let n = 2;
      Object.defineProperty(obj,'num',{
          get:function(){   //取 obj.num 屬性時會觸發 get 方法
              /*數據劫持*/
              //當你獲取這個屬性的時候,會調用
               n += 2;
              return n;
          },
       set(val){   //給 obj.num 賦值時會觸發 set 方法
         //val 是給 obj.num 賦值時的那個值 
       }

      });
      console.log(obj.num < 5 && obj.num > 5);//true
  /*num即小於5,又大於,就是應爲,第一次判斷obj.num時num=(n+=2)=4,符合了第一個條件,此時的n=4。
 讀到第二個判斷的時候,再次觸發函數,此時n+=以後爲6,又符合了第二個判斷條件,因此出現了true*/        
相關文章
相關標籤/搜索