1. 程式人生 > >js中屬性類型:數據屬性與訪問器屬性

js中屬性類型:數據屬性與訪問器屬性

func 自定義對象 有效 con 方法 delete code 字符串 參數

js中屬性類型分為兩種:數據屬性和訪問器屬性

在js中,對象都是由名值對構成的,名:就是我們所說的屬性名,值就是屬性對應的值(基本值、對象、方法)。

ECMA-262第5版定義了只有內部才用的特性,描述了屬性的各種特征,比如,這個屬性能否被刪除、能否被枚舉、能否被修改、以及讀取屬性的值。

這些特性是為了實現JavaScript引擎用的,因此在JavaScript中不能直接訪問他們。

1、先來說一下數據屬性

數據屬性:包含一個數據值的位置。在這個位置可以讀取和寫入值。數據屬性有4個描述其行為的特性

Configurable:表示能否通過delete刪除屬性,從而重新定義屬性,能否修改屬性的特性,或則能否把屬性修改為訪問器屬性

。我們一般在對象上自定義的屬性,它們的這個特性一般為true。

Enumberable:表示能否通過for-in循環返回屬性(枚舉),自定義的對象屬性,默認值為true。

Writable:表示能否修改屬性的值,自定義對象的屬性,這個特性值默認為true。

Value:包含這個屬性的數據值,讀取屬性值的時候從這個讀,寫入屬性值的時候,把新值保存在這個位置。這個特性的默認值為undefined。

ECMAScript5定義了一個修改屬性的這些默認特性的方法:Object.defineProperty();

這個方法接收三個參數:屬性所在的對象、屬性的名字(字符串形式)、一個描述符對象。其中描述符對象的屬性必須是:configurable、enumberable、writable、value,設置其中的一個或多個值,可以修改對應的特性值。例如:

    var person={};
    Object.defineProperty(person,"name",{
        writable:false,
        value:"Nicholas"
    });
    console.log(Object.getOwnPropertyDescriptor(person,"name"));//讀取屬性的特性的方法,後面會介紹
    console.log(person.name);//Nicholas
    person.name="Greg";
    console.log(person.name);//Nicholas

上面,對name屬性的兩個特性writable、value進行了設置,可見,我們更改name屬性的值是無效的,在嚴格模式下會報錯;

當用Object.defineProperty()創建一個新屬性時,若不指定configurable、enumberable、writable這些特性時,都是false,若果在原來設置過的基礎上設置其中的一個或多個,則無此限制。

另外,當設置configurable為false後,也就是把該屬性變成不可設置的,除delete不能刪除該屬性外,再次用Object.defineProperty()方法設置除writable特性外的其它特性時,在非嚴格模式時什麽都不會發生,在嚴格模式時會報錯。(同時configurable特性也設置不了true了!!!);

2、訪問器屬性:

訪問器屬性不包含數據值,他們包含一對兒getter和setter函數(不過,這兩個函數都不是必須的)。在讀取訪問器屬性時,會調用getter函數,這個函數負責返回有效的值;在寫入訪問器屬性時,會調用setter函數並傳入新值,這個函數負責決定如何處理數據。訪問器屬性有如下4個特性

configurable:表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或則能否把屬性修改為數據屬性。對於直接在對象上定義的屬性,這個特性的默認值為true。

enumberable:表示能否通過for-in來循環返回屬性。對於直接在對象上定義的屬性,這個特性的默認值為true。

get:讀取屬性時調用的函數。默認值為undefined

set:在寫入屬性時調用的函數。默認值為undefined

訪問器屬性不能直接定義,必須使用Object.defineProperty()來定義。請看下面的例子:

    var book={
        _year:2004,
        edition:1
    };
    //下邊給book對象設置一個year(訪問器屬性)
    Object.defineProperty(book,"year",{
        get:function(){
            return this._year;
        },
        set:function(newValue){
            if(newValue>2004){
                this._year=newValue;
                this.edition=newValue - 2004;
            }
        }
    });
    book.year =2005;
    console.log(book.edition);//1
    console.log(book._year);//2005
    console.log(book.year);//2005
    console.log(book);//{_year: 2005, edition: 1}

可見,創建的訪問器屬性,用console是打印不出來的,我們常見的使用訪問器屬性的方式就是上述這種方式,修改訪問器屬性,會導致其他屬性變化!!!

當然,不一定非要指定get和set,只指定get就是只能讀,不能寫,只指定set就是不能讀。

當然也可以同時定義多個屬性,用:Object.defineProperties()方法,利用這個方法可以通過描述符一次定義多個屬性,這個方法接收兩個參數,第一個參數是要添加和修改其屬性的對象,第二個參數(對象:描述符)的屬性與第一個對象中要添加或修改的屬性要一一對應。如:

    var book={};
    Object.defineProperties(book,{
        _year:{//定義一個數據屬性,其它為指定的特性值為false
            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;
                }
            }
        }
    });
    book.year=2003;
    console.log(book);//{_year: 2004, edition: 1}
    book.year=2005;
    console.log(book);//{_year: 2005, edition: 1}
    // Object.getOwnPropertyDescriptor();用來讀取給定屬性的描述符,這個方法有兩個參數,屬性所在的對象和要讀取其描述符的屬性名,返回一個對象。
    var descriptor=Object.getOwnPropertyDescriptor(book,"_year");//數據屬性
    var descriptor2=Object.getOwnPropertyDescriptor(book,"year");//訪問器屬性
    console.log(descriptor);//{value: 2005, writable: true, enumerable: false, configurable: false}
    console.log(descriptor2);//{get: ?, set: ?, enumerable: false, configurable: false}
Object.getOwnPropertyDescriptor();用來讀取給定屬性的描述符,這個方法有兩個參數,屬性所在的對象和要讀取其描述符的屬性名,返回一個對象。這個方法可以在任何瀏覽器使用。

js中屬性類型:數據屬性與訪問器屬性