摘要:中的函數(shù)本身就是對(duì)象,可以攜帶自身狀態(tài),另外還有化等函數(shù)式編程的方法讓函數(shù)緩存狀態(tài),基本上沒(méi)有仿函數(shù)存在的必要。
Functor
仿函數(shù)(Functor)是 C++ 里面一個(gè)重要的概念,簡(jiǎn)而言之就是使用重載了 operator() 運(yùn)算符的對(duì)象模仿函數(shù)的行為,帶來(lái)的收益是仿函數(shù)可以攜帶自身狀態(tài),普通的 C++ 函數(shù)不是對(duì)象,做不到這一點(diǎn)。
js 中的函數(shù)本身就是對(duì)象,可以攜帶自身狀態(tài),另外還有 curry 化等函數(shù)式編程的方法讓函數(shù)緩存狀態(tài),基本上沒(méi)有仿函數(shù)存在的必要。最簡(jiǎn)單的你可以這樣寫(xiě):
function foobar() { return foobar.a; } foobar.a = 1; var b = foobar(); // b=>1
這樣,foobar 就攜帶了自身狀態(tài) a,并且可以在函數(shù)體重訪問(wèn) a。
但是這里有一個(gè)問(wèn)題:函數(shù)體中 foobar.a 這一句是利用閉包實(shí)現(xiàn)的,其中 foobar 這個(gè)引用被寫(xiě)死了,從效果上看 foobar 成了一個(gè)單例。如果我想要多個(gè) foobar 實(shí)例怎么辦呢?
以及,我比較喜歡 this 指針,而不是閉包。面對(duì)這種情況,我更喜歡這樣的寫(xiě)法:
// 偽代碼 function foobar() { return this.b; } foobar.setB = function (val) { this.b = val } var foo = new foobar; foo.setB(1); var b = foo(); // b=>1js 實(shí)現(xiàn)
那么怎么實(shí)現(xiàn)呢?我之前寫(xiě)了一篇文章,里面說(shuō) js 不容易實(shí)現(xiàn)類(lèi)似的概念。但是當(dāng)時(shí)我沒(méi)細(xì)想,今天試了一下其實(shí)變動(dòng)一下接口,還是能實(shí)現(xiàn)類(lèi)似效果的。
基本的原理就是這樣:
function f() {...} var functor = f.bind(f);
讓一個(gè)函數(shù) bind 它自己,這樣它不就能用 this 訪問(wèn)自己了嗎?但是這里還有個(gè)問(wèn)題,bind 的返回結(jié)果并不是 f 自身而是另一個(gè)函數(shù),functor 的持有者在外部訪問(wèn)不到 f。所以這里還要用 js 的新 api defineProperty 處理一下,使得對(duì) functor 的某些屬性訪問(wèn),轉(zhuǎn)移到 f 上去。
完整的實(shí)現(xiàn)如下:
function makeFunctor(fn, props) { function thisFn() { return fn.apply(this, Array.prototype.slice.call(arguments)); } var ret = thisFn.bind(thisFn); for (var key in props) { if (!props.hasOwnProperty(key)) { continue; } Object.defineProperty(ret, key, { configurable : true, enumerable : true, get : function () { return thisFn[key]; }, set : function (value) { thisFn[key] = value; } }); ret[key] = props[key]; } return ret; }
通過(guò) makeFunctor,我們可以通過(guò)一個(gè)函數(shù) fn 創(chuàng)建很多個(gè) functor,每一個(gè)都有自身的狀態(tài),互不影響。并且在 fn 中我們可以使用 this 訪問(wèn)自身狀態(tài)。比如:
function hello () { alert("Hello, " + this.name); } hello.create = function () { makeFunctor(hello, { name : "Tom" }); } var ftHello = hello.create(); var ftHello2 = hello.create(); ftHello(); // Hello, Tom" ftHello.name = "Jack"; ftHello(); // Hello, Jack" ftHello2(); // Hello, Tom"
最后,這只是個(gè)腦洞!每個(gè)語(yǔ)言都有自身的規(guī)律和方法論。不要真的在項(xiàng)目里這么寫(xiě),除非你的項(xiàng)目目的就是創(chuàng)造漂亮的語(yǔ)法。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/86418.html
摘要:我們知道狀態(tài)機(jī)是表示有限個(gè)狀態(tài)以及在這些狀態(tài)之間的轉(zhuǎn)移和動(dòng)作等行為的數(shù)學(xué)模型。對(duì)照上面我們自己寫(xiě)的狀態(tài)機(jī)代碼可以看出的作用告訴狀態(tài)樹(shù)發(fā)生什么變化,及所需要的數(shù)據(jù)是什么。 前言 我之前開(kāi)發(fā)網(wǎng)站的時(shí)候一直用的是 Flux, 自從出了 Redux 之后由于種種原因沒(méi)有跟進(jìn)了解,最近手頭上的事情基本忙的差不多了,抽空閱讀了 Redux 的源碼,并整理了這篇博文。 先說(shuō)重點(diǎn): Redux 與 R...
摘要:在我們上面的例子里,的輸入和返回值是一樣的數(shù)據(jù)類(lèi)型,都是。所以我們可以寫(xiě)一個(gè)服務(wù)于函數(shù)的么答案是肯定的但怎么拆開(kāi)一個(gè)函數(shù)是個(gè)問(wèn)題簡(jiǎn)單點(diǎn)兒,你可以直接執(zhí)行這個(gè)函數(shù),然后用她的返回值。我們來(lái)拿試一下聲明了一個(gè)函數(shù)的參數(shù)及返回值的形態(tài)。 Functors 先看看如下代碼: function plus1(value) { return value + 1; } 這就是一個(gè)普通函數(shù),...
摘要:簡(jiǎn)單說(shuō),我想實(shí)現(xiàn)這么一個(gè)功能假設(shè)有一個(gè)對(duì)象,他的方法支持鏈?zhǔn)秸{(diào)用。本來(lái)是立即執(zhí)行的代碼,通過(guò)的包裝,成了一個(gè)函數(shù),我可以把存儲(chǔ)起來(lái)在任意時(shí)刻調(diào)用,相當(dāng)于執(zhí)行檢查。 我相信讀到本文標(biāo)題的人基本上是懵 B 的,我實(shí)在想不出更好的表述方法。簡(jiǎn)單說(shuō),我想實(shí)現(xiàn)這么一個(gè)功能: 假設(shè)有一個(gè)對(duì)象 foobar,他的方法支持鏈?zhǔn)秸{(diào)用。比如這樣: var foobar = new Foobar(); f...
摘要:函數(shù)式編程二拖延癥了好久,第二篇終于寫(xiě)出來(lái)了。如果你對(duì)熟悉的話應(yīng)該還記得,是可以調(diào)用來(lái)集中處理錯(cuò)誤的對(duì)于函數(shù)式編程我們也可以做同樣的操作,如果運(yùn)行正確,那么就返回正確的結(jié)果如果錯(cuò)誤,就返回一個(gè)用于描述錯(cuò)誤的結(jié)果。 JavaScript函數(shù)式編程(二) 拖延癥了好久,第二篇終于寫(xiě)出來(lái)了。 上一篇在這里:JavaScript函數(shù)式編程(一) 上一篇文章里我們提到了純函數(shù)的概念,所謂的純函數(shù)...
摘要:電子表格使用語(yǔ)言電子表格是辦公軟件的必備,我們最熟知的是微軟的。文中用框架來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的電子表格,所用代碼僅行。 showImg(https://segmentfault.com/img/remote/1460000019770011); 本文原創(chuàng)并首發(fā)于公眾號(hào)【Python貓】,未經(jīng)授權(quán),請(qǐng)勿轉(zhuǎn)載。 原文地址:https://mp.weixin.qq.com/s/Ob... 今天,...
閱讀 1392·2019-08-30 12:54
閱讀 1878·2019-08-30 11:16
閱讀 1621·2019-08-30 10:50
閱讀 2455·2019-08-29 16:17
閱讀 1275·2019-08-26 12:17
閱讀 1387·2019-08-26 10:15
閱讀 2396·2019-08-23 18:38
閱讀 793·2019-08-23 17:50