1. 程式人生 > >js 定義屬性 以及 getter 和 setter

js 定義屬性 以及 getter 和 setter

今天說一下js 的屬性設定,ES5中定義了兩種屬性,資料屬性和訪問器屬性(getter 和 setter)下面我總結了一些資料屬性 和 訪問器屬性的一些知識點。

一、資料屬性

資料屬性有四個描述其行為的特徵:

  • [[Configurable]]: 表示能否被 delete 刪除,預設為 true
  • [[Enumerable]]: 表示能否通過 for - in 迴圈返回屬性, 預設為true
  • [[Writable]]: 表示能否修改這個屬性的資料值,預設為true
  • [[Value]] : 包含這個屬性的值,讀取屬性值時,從這個位置讀,寫入時從這個位置寫入。

注意:要修改屬性的特性,要用ES5的 Object.defineProperty()來定義

該方法有三個引數,第一個為要處理的物件(注意不要帶引號),第二個為要處理的屬性名,第三個為一個物件,用於處理屬性。

例如:

 var person = {
     _name:"Jhone", // 前面加下橫線 ,下面會講
     sex:"man",
     age:24,
     height:170,
 } 
 person.fun = function () {
     console.log("my monthds")
 }

  Object.defineProperty(person,"name",{
     configurable:false, // 設定為通過delete 不能刪除
enumerable:false, // 設定為通過for - in 迴圈不能返回該屬性 writable:false, // 設定為不能修改屬性值 // value: 包含這個屬性的資料值,能寫入,能讀取 });

結果測試:

  delete(person.name);
  delete(person.sex);
  console.log(person.name); // Jhone 說明name不能被delete刪除
  console.log(person.sex); // underfind sex屬性被刪除

  person.name = 'King'; 
  console.log
(person.name); //Jhone 說明name不能被被修改 for(proto in person){ console.log(proto) } // 返回的結果中 沒有 name 屬性

二、訪問器屬性

訪問器屬性不包含資料值,他們包含一對 getter 和setter, 不過這兩個函式都不是必須的。在讀取屬性值時,會呼叫getter 函式,這個函式負責返回有效值;在寫入屬性值時,會呼叫seter函式並傳入新值,這個函式負責決定如何處理資料。

  • [[Configurable]]: 表示能否被 delete 刪除,預設為 true
  • [[Enumerable]]: 表示能否通過 for - in 迴圈返回屬性, 預設為true
  • [[Get]]: 在讀取時屬性是呼叫的函式,預設underfind
  • [[Set]]: 在寫入取時屬性是呼叫的函式,預設underfind

例如:(還是上面的物件)

Object.defineProperty(person,"age",{
    get:function(){
        return this._age;
     },
     set:function(newVlaue){
        if(newVlaue > 30){
            this.height = 185;
        }else{
            this.height =  170;
        }
     }
})

測試結果:

console.log(person.height);  //170 沒有設定屬性age(預設170)之前
people.age = 40;
console.log(person.height);   // 185 設定age為40後(大於30) height也變化了

get 和 set 方法不是必須的,當你不設定get方法時,

console.log(people.age); // underfind

但你不設定 set 時,對應的屬性是不能夠被寫入的。

三、定義多個屬性

有時候我們想定義多個屬性,ES5 為我們提供了 Object.defineProperties()方法;

例如:

 Object.defineProperties(person,{
    _nameTwo:{
        value:"LaoZhang"
    },
    nameTwo:{
        get:function(){
            return this._name;
        },
        set:function(newVlaue){
            console.log(newVlaue)
        }
    },
    sex:{
        set:function(newVlaue){
            console.log(newVlaue)
        }
    }
  })
  console.log(person.nameTwo) //LaoZhang
  person.sex = "man" // man

注意: 屬性用getter 去獲取時,要將屬性前加下劃線 “_”這是js的常用的記號,表示只能通過物件方法訪問。如果你沒有加,那麼 你用get 去獲取屬性時,瀏覽器可能會報錯,但是你在外部訪問時可以不用加, 如 console.log(person.nameTwo)

四、讀取屬性的特性

ES5為我們提供了一個Object.getOwnPropertyDescriptor() 方法來讀取屬性的特性
例如:

 var descriptor =Object.getOwnPropertyDescriptor(person,"name");

 console.log(descriptor.value) // Jhone
 console.log(descriptor.configurable) //true 預設為true,如果你更改了configurable,這裡會有變化

五、定義訪問器的舊有方法

上面所講的一些發方法,一般在IE9+ 能正常實現。要想在更早的IE版本實現要用非標準方法__defineGetter____defineSetter__

例如:

person.__defineGetter__("name",function(){
  return this._name;
})
person.__defineSetter__("name",function(newValue){
 console.log(newValue)
})