JS中的get & set


   之前在看《Javascript 高級程序設計》一書中遇到過getter和setter,但因當時難於理解,且覺得用處較小,沒有細看,今日突然遇到了一種使用get&set讀寫對象屬性的方式。

//字面量創建對象
var p={
    //對象的成員:屬性&方法
    name:"cj",
    work:function(){
        console.log("working....");
    },
    _age:18,    //一般常用下划線開頭,表示該屬性只能有對象的方法進行訪問。
    //get讀取p._age
    get age(){
        return this._age;
    },
    //set設置p._age
    set age(val){
        if(val<0||val>150){
            throw new Error("invalid value");
        }else{
            this._age=val;
        }
    }
};
console.log(p.age);   //18
console.log(p._age);  //18
p.age=30;
console.log(p.age);  //18
console.log(p._age);  //18

 

 

然后在網上搜到了一組類似的用法:

    //創建一個類  
    var Person = function() {
        //屬性:姓名,注意要屬性名與get和set的名稱不能重復否則會報錯  
        this._username = 'unknown';
        this._age = 0;
    }
    //在原型中給set和get方法  
    //在原型中get和set方法的名稱是一樣的,方便調用  
    Person.prototype = {
        set username(name) {
    //        console.log('調用username的set方法');
            this._username = name;
        },
        get username() {
    //        console.log('調用了username的get方法');
            return this._username;
        }
    }

    var p = new Person();
    console.log(p);
    console.log(p.username); //unknown
    p.username;
    p.username = 'foo';
    console.log(p.username);  //foo

 

 但是沒能查找到更多關於get和set的信息,只能琢磨一下getter和setter:

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

數據屬性包含一個數據值的位置。在這個位置可以讀取和寫入值。

 1、數據屬性:在使用字面量形式創建的對象中,直接定義在對象上的屬性,包含四個默認的屬性:

  (1)[[configurable]]:表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性。該特性默認值為true。

  (2)[[enumerable]]:表示能否通過for-in循環返回屬性。該特性默認值為true。

  (3)[[writable]]:表示能否修改屬性的值。該特性默認值為true。

  (4)[[value]]:包含這個屬性的數據值,讀取屬性值的時候,從這個位置讀;寫入屬性值的時候,把新值保存在這個位置上,該特性默認值為undefined。

如果需要修改數據屬性,需要使用ECMAScript5中的object.defineProperty()方法。

var p={
    name:"nicole"
};
Object.defineProperty(p,"name",{
   value:"abc"
})
console.log(p.name);   //abc

2、訪問器屬性:不包含數據值;他們包含一對兒getter&setter函數,有如下4個特性:

  (1)configurable:表示能否通過delete刪除屬性從而定義新的屬性,能否修改屬性的特性,或者能否把屬性修改為數據屬性。該特性默認值為true。

  (2)enumerable:表示能否通過for-in循環返回屬性。該特性默認值為true。

  (3)get:在讀取屬性時調用的函數。該特性默認值為undefined;

  (4)set:在寫入屬性時調用的函數。該特性默認值為undefined;

 

注:對於兩種屬性默認值的測試如下,並非書中說的默認為true,有的情況下默認為false:

 

 

tip:_ 下划線是一種常用的記號,用於表示只能通過對象方法訪問的屬性。

var book={
    _year:2004,
    edition:1
};
Object.defineProperty(book,"year",{    //跟數據屬性不一樣,此處的year是訪問器屬性,_year是數據屬性。
    get:function(){
        return this._year;
    },
    set:function(newValue){
        if(newValue>2004){
            this._year=newValue;
            this.edition+=newValue-2004;
        }
    }
})  
book.year=2005;
alert(book.edition);   //2

支持這種方法的瀏覽器有:IE9+(IE8只是部分實現),Firefox4+,Safari5+,Opera12+,Chrome.舊版創建訪問器屬性,一般都是用兩個非標准的方法:_defineGetter_()和_defineSetter_()

3、定義多個屬性

var book={};
Object.defineProperties(book,{
    _year:{
        writable:true,
        value:2004
    },
    edition:{
        writable:true,
        value:1
    },
    year:{
        get:function(){
            return this._year;
        },
        set:function(newValue){
            if(newValue>2004){
                this._year=newValue;
                this.edition+=newValue-2004;
            }
        }
    }
})
console.log(book._year);  //2004
console.log(book.edition);  //1
book.year=2005;
console.log(book.edition);  //2

使用ECMAScript5的Object.getOwnPropertyDescriptor(屬性所在的對象,屬性名稱),可以取得給定屬性的描述符,返回一個對象,對象包含相應的屬性。

如果是數據屬性,這個對象的屬性有:configurable,enumerable,writable,value;

如果是訪問器屬性,這個對象的屬性有:configurable,enumerable,get,set;

支持這個方法的瀏覽器有:IE9+,Firefox4+,Safari5+,Opera12+,Chrome。

++++

var descriptor=Object.getOwnPropertyDescriptor(book,"_year");
console.log(descriptor);
var descriptor2=Object.getOwnPropertyDescriptor(book,"year");
console.log(descriptor2);

第一個_year是數據屬性,第二個year是訪問器屬性。所以最終打印出的結果如下:

 

所以看完這里,仍然不理解最初遇到的那種寫法是為何,姑且當做是在字面量對象中創建了訪問器屬性,來讀寫數據屬性吧。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM