Getter 和 Setter 的定義

 

Getter 和 Setter 的定義

Getter 是用來取得指定屬性的值的方法。Setter 是用來設定指定屬性的值的方法。你可以在所有預先定義的核心物件或使用者定義的物件(這類可支援新屬性的附加)中定義 Getter 和 Setter。為了定義 Getter 和 Setter,需要使用物件的字面表達語法。

JavaScript 1.8.1 note

自 JavaScript 1.8.1 起,在設定物件和陣列裡的初始化子的屬性時,不再可以呼叫 Setter。

以下的 JS shell 會話說明了 Getter 和 Setter 是如何在使用者定義的物件 o 裡運作的。JS shell 是一種應用程式,可讓開發者在分批模式或互動性的測試 JavaScript 代碼。

js> var o = {a:7, get b() {return this.a+1;}, set c(x) {this.a = x/2}};
[object Object]
js> o.a;
7
js> o.b;
8
js> o.c = 50;
js> o.a;
25

o 物件的屬性為︰

  • o.a - 數字
  • o.b - 返回 o.a 加 1 的 Getter
  • o.c - 把 o.a 的值設為所屬的 o.c 的值的一半的 Setter

另一種(Mozilla 限定)表示成一行的方式,也支援在物件的屬性上(如 "foo-bar")設定 Getter 和 Setter,其中物件需要加上引號。

var o = {a:7, 'b' getter:function () {return this.a + 1;}, c setter:function (x) {this.a = x / 2;}};

請注意定義在物件的字面表達中的 Getter 和 Setter 的函數名稱使用的〝[gs]et property()〞(有別於稍後介紹的 __define[GS]etter__)並不是 Getter 本身的名稱,即使 [gs]et propertyName(){ } 語法可能會使你把他誤解成別的事物。若要命名在 Getter 或 Setter 之中的函數的名稱,就使用〝[gs]et property()〞語法,把 Getter 的名稱放在 get 或 set 後面,然後在其後面放上函數的名稱。下面的範例示範如何在物件的字面表達中命名 Getter 函數︰

var objects = [{get a b(){return 1}},
               {a getter:function b(){return 1}},
               {"a" getter:function b(){return 1}}];

for (var i=0; i<objects.length; ++i)
    print(objects[i].__lookupGetter__("a")) // 為每一個 Getter 輸出 "function b(){return 1}"。

這次 JavaScript shell 會話說明 Getter 和 Setter 如何擴充 Date 的原型,給所有預先定義的 Date 類別的實體加入 year 屬性。他使用了 Date 類別中既存的 getFullYear 以及 setFullYear 方法,以支援 year 屬性的 Getter 和 Setter。

以下語句針對 year 屬性定義 Getter 和 Setter︰

js> var d = Date.prototype;
js> d.__defineGetter__("year", function() { return this.getFullYear(); });
js> d.__defineSetter__("year", function(y) { this.setFullYear(y); });

以下語句在 Date 物件中使用 Getter 和 Setter︰

js> var now = new Date;
js> print(now.year);
2000
js> now.year = 2001;
987617605170
js> print(now);
Wed Apr 18 11:13:25 GMT-0700 (Pacific Daylight Time) 2001
在 JavaScript 1.5 的開發期間,這些是內含用來在既存的物件上定義新的 Getter 或 Setter 的 getter =setter = 表達式的摘要,這些語法現在已被廢棄,將會在目前的 JS 1.5 引擎中引發警告,在未來的版本中將會變成語法錯誤。這些都應該要避免。

概要

原則上,Getter 和 Setter 可以

  • 使用 物件的初始化子 定義,或
  • 稍後在任意的時間點上對任意的物件使用 Getter 或 Setter 的添加方法來加入。

當要使用 物件的初始化子 定義 Getter 和 Setter 的時候,你所需要做的是在 Getter 方法的前面加上 get 以及在 Setter 方法的前面加上 set。當然,Getter 方法不可以接受參數,Setter 方法則只能有一個參數(用來設定的新值)。舉例如下︰

o = {
  a:7,
  get b() { return this.a+1; },
  set c(x) { this.a = x/2; }
};

也可以在物件建立之後的任何時間點上,使用兩個稱作 __defineGetter____defineSetter__ 的特殊方法,把 Getter 和 Setter 加到物件裡。這兩個方法需要 Getter 或 Setter 的名稱以字串的形式作為第一個參數。第二個參數是用來呼叫的函數作為 Getter 或 Setter。舉例如下(延用之前的例子):

o.__defineGetter__("b", function() { return this.a+1; });
o.__defineSetter__("c", function(x) { this.a = x/2; });

這兩種形式的選擇,取決於你的程式設計風格以及手上的工作。如果你已經在定義原型的時候,使用了物件的初始化子,或許你在大多數時候都會選擇第一種形式。這種形式更加密集且自然。然而,如果你需要稍後加入 Getter 和 Setter – 因為你並未編寫原型或實際的物件 – 這時第二種形式就是唯一可行的形式。第二種形式或許是 JavaScript 的動態性質中最佳的表現 – 但這會使代碼難以閱讀和理解。

在 Firefox 3.0 以前,Getter 和 Setter 並不支援 DOM 元素。舊版本的 Firefox 會默默的出錯。如果需要這些例外,修改 HTMLElement 的原型 (HTMLElement.prototype.__define[SG]etter__),並且避免拋出例外。

在 Firefox 3.0 中,在已定義的原型上定義 Getter 或 Setter 將會拋出例外。必須事先刪除這些屬性。舊版本的 Firefox 則沒有這個問題。

參閱

文件標籤與貢獻者

 此頁面的貢獻者: jigs12, teoli, happysadman
 最近更新: jigs12,