iT邦幫忙

2022 iThome 鐵人賽

0
Modern Web

就是要搞懂 JavaScript 啦!系列 第 42

Day42 Prototype 遮蔽:一葉障目,不見泰山

  • 分享至 

  • xImage
  •  

在討論多型(Polymorphism)的章節中,有提到了多型是利用原型鍊的「遮蔽(Shadowing)」來達成,不過遮蔽在實際狀況下有些需要注意的細節。

在為一個屬性賦值,如 obj.propA = "A"; 時,可能會有三種情況:

  1. obj 內部與原型鍊上都找不到 propA 屬性
  2. obj 內部擁有一個 propA 屬性
  3. obj 沒有 propA 這個屬性,但原型鍊上有

1 的狀況下,obj 會新增 propA 這個屬性,並且直接賦值;2 的狀況中如果 propA 並未設置為 writable: false,則會覆蓋原本的值;3 的情況則因為細節會有些微妙的不同。

遮蔽的條件

執行 obj.propA = "A"; 時,如果 obj 本身沒有 propA 這個屬性,但原型鍊上有,這時候就需要檢查上層物件的 propA

如果這個屬性的 writabletrue,則這個賦值會被忽略,不會發生遮蔽(在嚴格模式下,程式則會拋出錯誤):

const objProto = {};
Object.defineProperty(objProto, "propA", {
  value:2,
  writable: false
})

const obj2 = Object.create(objProto);
console.log(obj2.propA); // 2
obj2.propA = 4
console.log(obj2.propA); // 2

而如果這個屬性擁有設值器(setter),則在賦值時會調用這個設值器,並將結果添加到 objpropA 上:

var objProto = {
	get propA() {
		return this.privateProp;
	},
	set propA(val) {
		this.privateProp = val * 2;
	}
};

objProto.propA = 2;
console.log(objProto.propA); // 4

const obj2 = Object.create(objProto);
console.log(obj2.propA); // 4
obj2.propA = 8
console.log(obj2.propA); // 16
console.log(objProto.propA); // 4

如果以上兩者皆非,則 obj 上會直接添加屬性 propA,並對上層物件的 propA 形成遮蔽:

var objProto = {
  propA: 2
};

const obj2 = Object.create(objProto);
console.log(obj2.propA); // 2
obj2.propA = 4
console.log(obj2.propA); // 4
console.log(objProto.propA); // 2

參考資料


上一篇
Day41 Prototype OOP 混合:不需要繼承的繼承
下一篇
Day43 Prototype 委託:自己辦不到的,就外包出去吧
系列文
就是要搞懂 JavaScript 啦!73
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言