2015-12-31

Javascript 的 instance property 與 static property

Javascript 的 instance property 很容易實做,只要用 this 就可以了。
function Counter() {
  this.count = 1;
}

var c1 = new Counter();
console.log(c1.count++); // 1
console.log(c1.count++); // 2
console.log(c1.count++); // 3

var c2 = new Counter();
console.log(c2.count++); // 1
console.log(c2.count++); // 2
console.log(c2.count++); // 3
但是 static property 就有點傷腦筋了,先來看正常的部份,將 property 直接掛在 prototype 上,改了其中一個 instance 的 prototype property,其他 instance 的 prototype property 也跟著改變,表示是共用同一個物件,可以視為 static property。
Counter.prototype.date = new Date();

console.log(c1.date); // Thu Dec 31 2015 22:18:39 GMT+0800 (台北標準時間)
console.log(c2.date); // Thu Dec 31 2015 22:18:39 GMT+0800 (台北標準時間)

c1.date.setFullYear(2000); // 改了 c1.date,c2.date 也連帶受影響
console.log(c1.date); // Sun Dec 31 2000 22:19:25 GMT+0800 (台北標準時間)
console.log(c2.date); // Sun Dec 31 2000 22:19:25 GMT+0800 (台北標準時間)
除了上面的 Date 格式,陣列也有一樣的效果。
Counter.prototype.array = [];

c1.array.push(1);
c1.array.push(2);
console.log(c1.array); // [1, 2]

c2.array.push(3);
c2.array.push(4);
console.log(c2.array); // [1, 2, 3, 4]
接下來是傷腦筋的地方,在 int 格式變數的修改不會影響其他 instance。
Counter.prototype.integer = 0;
c1.integer = 1;
console.log(c1.integer); // 1
console.log(c2.integer); // 0
字串格式也是不會影響其他 instance。
Counter.prototype.string = 'a';
c1.string = 'b';
console.log(c1.string); // b
console.log(c2.string); // a
書上網路上找不到解答,只能自己猜測。

應該是 reference 的關係,數值和字串在 Javascript 是 pass by value,而物件格式的 Date 與陣列則是 pass by reference。

所以透過 prototype 來實做的 static property 只能算是半套,再想想囉。
---
---
---

2 則留言:

  1. 可把 Counter 當作 Java 中的 Class,所以可寫下面的程式表示 static property:
    Counter.staticCount = 0;
    Counter.staticName = 'Counter';

    參考範例:https://jsfiddle.net/7ymxu44a/

    回覆刪除
    回覆
    1. 原來是這樣,我被prototype 綁架了,感謝。

      刪除