摘要:引子獨(dú)家解析原型繼承已經(jīng)比較全面的分析了自定義函數(shù)類型,內(nèi)置基本類和內(nèi)置對(duì)象類型的的以及的原型鏈。鑒于函數(shù)是的一等公民,另辟新篇介紹函數(shù)的原型及其應(yīng)用。函數(shù)本身也是對(duì)象,它遵循獨(dú)家解析原型繼承所描述的自定義函數(shù)類型對(duì)象的原型法則。
引子
獨(dú)家解析Javascript原型繼承已經(jīng)比較全面的分析了自定義函數(shù)類型,JS內(nèi)置基本類(undefined, null, bool, number, string, symbol)和JS內(nèi)置對(duì)象類型(Error, Date, Function)的design-time的prototype, 以及run-time的__proto__原型鏈。鑒于函數(shù)是JS的一等公民,另辟新篇介紹函數(shù)的原型及其應(yīng)用。
JS函數(shù)類型的構(gòu)造通常情況下定義一個(gè)函數(shù):
function add1(a, b) { return a + b; } console.log(add1(1,2)) //3
通過(guò)new Function也能構(gòu)造:
var add2 = new Function("a", "b", "return a + b"); console.log(add2(1,2)) //3
兩種方式達(dá)到的目的是一致的。而add1和add2的run-time __proto__都是Function.prototype, 可以看作add1和add2都是透過(guò)new Function構(gòu)造出來(lái)的,而function關(guān)鍵子就是調(diào)用new Function構(gòu)造的便利途徑。
add1.__proto__ = Function.prototype //true add2.__proto__ = Function.prototype //true
函數(shù)本身也是對(duì)象,它遵循獨(dú)家解析Javascript原型繼承所描述的自定義函數(shù)類型對(duì)象的原型法則。
//add1 創(chuàng)自于Function類型,是Function的實(shí)例 add1.__proto__ //[Function] add instanceof Function //true // add1 也繼承了object類型的原型 add1.__proto__.__proto__ //{} add1 instanceof Object //true // 所以add1 run-time __proto__原型鏈的頂端同樣是null add1.__proto__.__proto__.__proto__ // nullAOP編程實(shí)現(xiàn)
至此我們了解到,透過(guò)funtion關(guān)鍵字定義的函數(shù),實(shí)質(zhì)是Fuction類型的實(shí)例,和通過(guò)new Function方式構(gòu)造本身是一樣的。所以我們通過(guò)修改Function的design-time的prototype,來(lái)實(shí)現(xiàn)面向切面編程(AOP)
值得一提的是:我們(程序員)一般情況下只推薦修改design-time的prototype,而不去更改run-time的__proto__, 否則修改run-time的__proto__會(huì)造成程序難以維護(hù)和閱讀,增加不確定的運(yùn)行錯(cuò)誤。Object.setPrototypeOf可以更改對(duì)象實(shí)例run-time的__proto__
面向切面編程(AOP,Aspect-Oritented Programming), 簡(jiǎn)而言之,可理解為函數(shù)調(diào)用時(shí),在該函數(shù)執(zhí)行前或/和執(zhí)行后做一些通用的工作,比如做log,記錄執(zhí)行時(shí)間等。這需要一個(gè)代理函數(shù),把原始函數(shù)打扮成具有做log等功能的新函數(shù)。實(shí)際中調(diào)用該代理函數(shù)
function foo() { console.log("foo runs"); } foo(); // foo runs
現(xiàn)在我們想在foo函數(shù)執(zhí)行前后分別打印log,而不修改foo函數(shù)本身。
Function.prototype.before = function() { var _self = this; return function() { console.log("before foo calls"); return _self.apply(this, arguments); } } Function.prototype.after = function() { var _self = this; return function() { var ret = _self.apply(this, arguments); console.log("after foo calls"); return ret; } } //這里foo就具有了執(zhí)行前后打印log的功能 foo = foo.before().after(); foo(); // before foo calls // foo runs // after foo calls
把打印log的功能提出來(lái),做成更通用的邏輯。
Function.prototype.before = function(beforeFn) { var _self = this; return function() { beforeFn.apply(this, arguments); return _self.apply(this, arguments); } } Function.prototype.after = function(afterFn) { var _self = this; return function() { var ret = _self.apply(this, arguments); afterFn.apply(this, arguments); return ret; } } //包裝成具有l(wèi)og功能的新的foo函數(shù) foo = foo.before(function() { console.log("foo enters") }).after(function(){ console.log("foo exits") }); foo(); // foo enters // foo runs // foo exits
由此,可把函數(shù)調(diào)用和通用的log能功能掛接(hook)起來(lái)了。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/84030.html
摘要:支持的類型的內(nèi)置數(shù)據(jù)類型羅列如下自定義自定義這三種類型的賦值是同類似的。這根不同,這因?yàn)槭菦]有包裝類新增的基本類型,只支持函數(shù)式賦值,不支持字面量和函數(shù)構(gòu)造。 JavaScript支持的類型 JS的內(nèi)置數(shù)據(jù)類型羅列如下: undefined null bool number string function object Function Date ...
摘要:面向?qū)ο髮?shí)現(xiàn)代碼動(dòng)物發(fā)聲汪汪喵喵調(diào)用代碼動(dòng)物發(fā)聲喵喵動(dòng)物發(fā)聲汪汪當(dāng)要增加一種動(dòng)物時(shí),只需增加一個(gè)繼承,不會(huì)影響其他已有的動(dòng)物邏輯。所以的繼承和的原型繼承,可謂殊途同歸。 傳統(tǒng)面向?qū)ο蟮睦^承和多態(tài) 我們知道C++/Java/C#等面向?qū)ο笳Z(yǔ)言,都原生地支持類的繼承。繼承的核心作用大抵是創(chuàng)建一個(gè)派生類,并使其復(fù)用基本類(即父類)的字段和/或方法。并且派生類可以重寫基本類的方法。這樣基本類和...
摘要:每一個(gè)由構(gòu)造函數(shù)創(chuàng)建的對(duì)象都會(huì)默認(rèn)的連接到該神秘對(duì)象上。在構(gòu)造方法中也具有類似的功能,因此也稱其為類實(shí)例與對(duì)象實(shí)例一般是指某一個(gè)構(gòu)造函數(shù)創(chuàng)建出來(lái)的對(duì)象,我們稱為構(gòu)造函數(shù)的實(shí)例實(shí)例就是對(duì)象。表示該原型是與什么構(gòu)造函數(shù)聯(lián)系起來(lái)的。 本文您將看到以下內(nèi)容: 傳統(tǒng)構(gòu)造函數(shù)的問(wèn)題 一些相關(guān)概念 認(rèn)識(shí)原型 構(gòu)造、原型、實(shí)例三角結(jié)構(gòu)圖 對(duì)象的原型鏈 函數(shù)的構(gòu)造函數(shù)Function 一句話說(shuō)明什么...
摘要:設(shè)計(jì)模式是以面向?qū)ο缶幊虨榛A(chǔ)的,的面向?qū)ο缶幊毯蛡鹘y(tǒng)的的面向?qū)ο缶幊逃行┎顒e,這讓我一開始接觸的時(shí)候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設(shè)計(jì)模式必須要先搞懂面向?qū)ο缶幊?,否則只會(huì)讓你自己更痛苦。 JavaScript 中的構(gòu)造函數(shù) 學(xué)習(xí)總結(jié)。知識(shí)只有分享才有存在的意義。 是時(shí)候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...
摘要:使用新的易用的類定義,歸根結(jié)底也是要?jiǎng)?chuàng)建構(gòu)造函數(shù)和修改原型。首先,它把構(gòu)造函數(shù)當(dāng)成單獨(dú)的函數(shù)且包含類屬性集。該節(jié)點(diǎn)還儲(chǔ)存了指向父類的指針引用,該父類也并儲(chǔ)存了構(gòu)造函數(shù),屬性集和及父類引用,依次類推。 原文請(qǐng)查閱這里,略有刪減,本文采用知識(shí)共享署名 4.0 國(guó)際許可協(xié)議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請(qǐng)查閱這里。 這是 JavaScript 工作原理的第...
閱讀 2282·2021-09-27 13:35
閱讀 569·2019-08-30 15:55
閱讀 820·2019-08-30 15:53
閱讀 567·2019-08-30 15:52
閱讀 2155·2019-08-30 12:59
閱讀 2280·2019-08-29 16:42
閱讀 1443·2019-08-26 18:26
閱讀 2478·2019-08-26 13:48