一文詳解JavaScript中的Mixin
類的出現(xiàn)最終使 JavaScript
非常容易使用繼承語法,JavaScript
類比大多數(shù)人意識到的更強(qiáng)大,它是構(gòu)建真正的 mixins
的良好基礎(chǔ)。
什么是 Mixin
在 JavaScript
中,把不同類的行為集中到一個類是一種常見的模式,雖然 ES6
沒有顯示支持多類繼承,但通過現(xiàn)有特性可以輕松地模擬這種行為。
Object.assign()
方法是為了混入對象行為而設(shè)計的,只有在需要混入類的行為時才有必要自己實現(xiàn)混入表達(dá)式,如果只是需要混入多個對象的屬性,那么使用 Object.assign()
就可以了。
在集成或者實例化時,JavaScript
的對象機(jī)制并不會自動執(zhí)行復(fù)制行為,簡單來說,在 JavaScript
中只有對象,并不存在可以被實例化的類,一個對象并不會被復(fù)制到其他對象,它們會被關(guān)聯(lián)起來。
在其他語言中類表現(xiàn)出來的都是復(fù)制行為,因此 JavaScript
開發(fā)者也想出了一個方法來模擬類的復(fù)制行為,這個方法就是混入。
那么在接下來的內(nèi)容中我們會看到兩種類型的混入,它們分別是顯示混入和隱式混入。
顯示混入
首先我們舉一個簡單的例子,在這里我們實現(xiàn)一個 mixin(...)
函數(shù),這個功能在許多庫和框架中被稱為 extend
,具體代碼如下所示:
function mixin(source, target) { for (const key in source) { if (!(key in target)) target[key] = source[key]; } return target; }
接下來我們實現(xiàn)一個 foo
類 和 bar
類,然后將兩個類進(jìn)行 mixin
,生成一個新的類,具體代碼如下所示:
const bar = { technical: function () { console.log("跳"); }, moment: function () { this.technical(); }, }; const foo = { nickname: "xun", hobby: "nba", age: 18, moment: function () { bar.moment.call(this); }, }; console.log(mixin(bar, foo));
現(xiàn)在返回的新對象中就有了一份 bar
對象的屬性和函數(shù)的副本了,從技術(shù)角度來說,函數(shù)實際上沒有被復(fù)制,復(fù)制的是函數(shù)引用。
所以返回的新對象中的屬性 thchnical
方法只是從 bar
中復(fù)制過來的對與 moment
函數(shù)的引用,相反 moment()
就是直接從 bar
中復(fù)制了值 1。
foo
已經(jīng)有了 moment
方法,所以這個屬性引用并沒有被 mixin
重寫,從而保留了 foo
中定義的同名方法,實現(xiàn)了子類對子類屬性的重寫。
顯示混入模式的一種變體被稱為 寄生繼承
,它既是顯示的又是隱式的,具體代碼如下所示:
function Foo() { this.nickname = "moment"; } Foo.prototype.ignition = function () { console.log("小黑子"); }; Foo.prototype.小黑子 = function () { this.ignition(); console.log("叼毛"); }; // 寄生類 function Bar() { const foo = new Foo(); foo.age = 18; const 你小子 = foo.小黑子; foo.小黑子 = function () { 你小子.call(this); console.log("不是所有的牛奶都是特侖蘇"); }; return foo; } const result = new Bar(); console.log(result);
該代碼的最終輸出結(jié)果如下所示:
就像你看到的一樣,首先我們復(fù)制一份 Foo
父類對象的定義,然后混入子類獨享的定義。
隱式混入
隱式混入示例代碼如下所示:
const something = { cool: function () { this.greeting = "hello"; this.count = this.count ? this.count + 1 : 1; }, }; console.log(something.cool()); // undefined console.log(something.greeting); // hello console.log(something.count); // 1 const another = { cool: function () { something.cool.call(this); }, }; console.log(another.cool()); // undefined console.log(another.greeting); // hello console.log(another.count); // 1
在上面代碼中通過在構(gòu)造函數(shù)調(diào)用或者方法調(diào)用中使用 something.cool.call(this)
,讓我們實際上 借用
了函數(shù) something.cool()
函數(shù)并在 another
的上下文中調(diào)用了它(通過 this
指向),最終的結(jié)果是 something.cool()
函數(shù)中的賦值操作都會應(yīng)用在 another
對象上而不是 something
對象上。
因此我們把 something
的行為混入到了 another
中。
總結(jié)
混入模式可以用來模擬類的賦值行為,但是通常會產(chǎn)生丑陋并且脆弱的語法,這會讓代碼更加難懂并且難以維護(hù)。
此外,顯示混入實際上無法完全模擬類的賦值行為,因為對象或者函數(shù)只能復(fù)制引用,無法復(fù)制引用對象或者函數(shù)本身,忽視這一點會導(dǎo)致許多問題。
到此這篇關(guān)于一文詳解JavaScript中的Mixin的文章就介紹到這了,更多相關(guān)JavaScript Mixin內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在實例中重學(xué)JavaScript事件循環(huán)
這篇文章主要介紹了在實例中重學(xué)JavaScript事件循環(huán),幫助大家更好的理解和學(xué)習(xí)JavaScript,感興趣的朋友可以了解下2020-12-12關(guān)于JavaScript中var聲明變量作用域的推斷
這個問題其實之前困擾了我很久。如今終于想明白了,特來分享,如果有錯誤的地方,請幫忙指正,我會隨時回來修正滴。2010-12-12通過js動態(tài)創(chuàng)建標(biāo)簽,并設(shè)置屬性方法
下面小編就為大家分享一篇通過js動態(tài)創(chuàng)建標(biāo)簽,并設(shè)置屬性方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-02-02各種常用瀏覽器getBoundingClientRect的解析
getBoundingClientRect2009-05-05JavaScript逆向調(diào)試技巧總結(jié)分享
當(dāng)我們抓取網(wǎng)頁端數(shù)據(jù)時,經(jīng)常被加密參數(shù)、加密數(shù)據(jù)所困擾,如何快速定位這些加解密函數(shù),尤為重要,下面這篇文章主要給大家介紹了關(guān)于JavaScript逆向調(diào)試技巧的相關(guān)資料,需要的朋友可以參考下2022-06-06php利用curl獲取遠(yuǎn)程圖片實現(xiàn)方法
這篇文章主要介紹了php利用curl獲取遠(yuǎn)程圖片實現(xiàn)方法,curl要求php環(huán)境支持,需要的朋友可以參考下2015-10-10