總結第五章,js中的[[prototype]]機制就是物件之間的關聯關係。
想要學習更直觀的使用[[prototype]],必須認識到它代表了一種不同於類的設計模式。
類設計模式鼓勵你在繼承時使用方法重寫(和多型),子類的許多行為可以先「抽象」到父類然後再用子類進行特殊化(重寫)。
例:
父類task,定義所有任務都有的行為。子類xyz、abc繼承task,並新增一些特殊的行為來處理對應的任務。
相比面向類(物件導向,oop),這種編碼風格稱為物件關聯,(oloo, objects linked to other objects)。
例:
定義乙個task物件,包含所有任務都可以使用的具體行為。接著對於每個任務(xyz、abc)都定義乙個物件來儲存對應的資料和行為。你會把特定的任務物件都關聯到task功能物件上,讓它們在需要的時候進行委託。
委託行為意味著某些物件(xyz)在找不到屬性或者方法引用時會把這個請求委託給另乙個物件(task)。這是一種極其強大的設計模式,和父類、子類、繼承、多型等概念完全不同。在你的腦海中物件並不是按照父類到子類的關係垂直組織的,而是通過任意方向的委託關聯併排組織的。
1)、互相委託(禁止):
你無法在兩個或兩個以上互相(雙向)委託的物件之間建立迴圈委託。
2)、除錯:
物件關聯風格的**中,不需要關注誰「構造了」物件,瀏覽器除錯中「建構函式名稱」的跟蹤沒有意義。
(「原型」)物件導向風格:
function foo(who)
foo.prototype.identify = function () ;
function bar(who)
bar.prototype = object.create(foo.prototype);
bar.prototype.speak = function () ;
var b1 = new bar("b1");
var b2 = new bar("b2");
b1.speak();
b2.speak();
物件關聯風格:
foo = ,
identify: function ()
};bar = object.create(foo);
bar.speak = function () ;
var b1 = object.create(bar);
b1.init("b1");
var b2 = object.create(bar);
b2.init("b2");
b1.speak();
b2.speak();
可以明顯看出,下面的**更加簡潔。我們只是把物件關聯起來,並不需要那些既複雜又令人困惑的模仿類的行為(建構函式、原型以及new)。
以web開發中非常典型的前端常見:建立ui控制項為例。
es6中的語法糖「class」可以極大地改善醜陋地顯式偽多型。
es6中引入class關鍵字,可以更簡潔地定義類方法。同時在es6中可以在任意物件的字面形式中使用簡潔方法宣告。但是有乙個缺點:自我引用(遞迴、事件(解除)繫結,等等)更難。
內省就是檢查例項的型別。類例項的自省主要目的是通過建立方式來判斷物件的結構和功能。
js中可以使用instanceof進行自省,也可以利用鴨子型別:
if (a1.something)
行為委託是一種設計模式,認為物件之間是兄弟關係,互相委託,而不是父類和子類的關係。
物件關聯是一種編碼風格,它倡導的是直接建立和關聯物件,不把它們抽象成類。
《你不知道的JS(上捲 )》 一 關於this
function identity var me var you identity.call me kyle identity.call you reader 觀察上面的 使用了this,identity函式就不再需要為每乙個物件編寫不同版本的函式。回想之前學習的詞法作用域,如果我們想要使用詞法作用...
《你不知道的JS(上捲 )》 二 詞法作用域
作用域共有兩種主要的工作模型。普遍被採用的的是第一種,詞法作用域。另一種為動態作用域,被bash指令碼 perl中的一些模式所採用。第一章提到過編譯階段之一 詞法分析。詞法作用域就是定義在詞法階段的作用域,即詞法作用域由你在寫 時將變數和塊作用域寫在 來決定的,大部分情況下詞法分析器處理 時會保持作...
你可能不知道的JS函式
日常業務寫的太多已經麻痺了神經,很多本該知道的知識早已拋之腦後,大家都知道在js中函式是一等公民,但是竟然連它的特性都不清楚,真是慚愧。在日常業務開發中,通常都會在資料中給乙個預設值,然後在請求後端資料後替換掉預設值,如果完全替換整個物件肯能並不是我們想要的,也可能會出現一些為止的錯誤,又或者需要對...