JavaScript 王國旅行的繼續(xù)邀摆,連對象也沒有怎么玩轉“封裝纵顾,繼承,多態(tài)”栋盹?


本文為 碼農翻身 微信公眾號投稿施逾,未經碼農翻身同意禁止轉載


又見 JSON 酒館

Java 小王子在 JavaScript 王國待了也有一段時間,這里雖然不像 Java 帝國那樣規(guī)范嚴苛例获,但也因此千奇百怪汉额,五光十色。

要說小王子最喜歡待的地方榨汤,那還是人來人往的 JSON 酒館蠕搜,不僅有上好的酒菜,還有機會認識到各式各樣的人收壕。這不妓灌,一來二去他已經和上回認識的眼鏡官員成了朋友轨蛤,甚至私底下還稱兄道弟的。
(參見上回)

今天小王子又和眼鏡大哥一起約來吃酒虫埂。才寒暄了幾句祥山,筷子還沒動,酒館門口就發(fā)生了一點騷動告丢。只見來了一位看起來像是教書先生的精瘦男子枪蘑,旁邊還有些隨從。
“...... 大哥岖免,這人什么來頭岳颇,氣度不凡啊÷妫”小王子悄聲向旁邊的眼鏡官員問到话侧。
“哈哈,他是函數式大主教闯参,最近他們教派的信眾激增啊瞻鹏,真是風水輪流轉÷拐”
“函數式新博?以前隨父親經商途中是聽說過他們的事情,好像非常古老而且高深莫測啊脚草,據說只有學者和虔誠的教徒才會加入他們赫悄,怎么最近也接收新人了?”
“小弟果然是見多識廣馏慨,不錯埂淮,在很久以前的確是這樣,不過為何有大批新教徒這種事情也不在我的管轄范圍內啊写隶,所以也不太清楚倔撞。但是畢竟我是本國語言規(guī)范審查官,還是與他打過一些交道慕趴。不妨我們邀請他來一起喝酒痪蝇,你親自問他≈确。”
小王子本來聽到眼鏡大哥也不了解情況正有些失望霹俺,突然得知可以直接面對面打探對方的底細,頓時興奮了起來毒费。
“那太好了丙唧!”

“這不是眼鏡老弟么,別來無恙啊觅玻∠爰剩”
“主教兄培漏,甚好甚好,要不這頓我請胡本?小二牌柄!”
飯菜上桌,互相客套了幾句之后侧甫,話題就開始了珊佣。
“主教兄,這是我最近認識的朋友披粟,年紀輕輕就周游四方咒锻,他有些事情要問你∈靥耄”
“哦惑艇?”函數式主教把目光放了過來,“你有何打探拇泛?”
“久問貴教派向來神秘滨巴,為何最近有如此多的新教徒加入呢?”
“哈俺叭,這個嘛 ... 現在的年輕人都不喜歡條條框框恭取,本教向來以簡潔強大著稱,自然就受歡迎了熄守』嗷纾”

小王子心想,這個主教倒也是有話直說自賣自夸柠横,不過難道沒了面向對象這種強大的武器,他還能變出怎么樣的花兒來课兄?
“那還敢請教大主教牍氛,依你看要怎么實現 Animal, Cat, Dog 這些對象呢?”想了一會兒烟阐,小王子認為不如直接發(fā)問搬俊。
“這個嘛,本教派并無對象這種說法蜒茄,不過如果你愿意唉擂,也可以構造一個對象出來,只需要......”
“我們不用對象~”檀葛,還沒等著主教說完玩祟,旁邊的妹子突然發(fā)話了。
“哦屿聋,小萊空扎,你來說吧藏鹊。”這位被叫做小萊的少女像是主教的助手转锈,看起來深得主教信任盘寡。
“嘻嘻,主教大人說的太復雜了撮慨,其實實現你說的那些根本不用什么對象竿痰。”
“哦砌溺?那該怎么做影涉?”小王子頓時來了興趣。


函數的翻身

“你想啊抚吠,搞出來這些貓啊狗啊的常潮,不就是想讓他們都可以吃東西么?干嘛要封裝到一個對象中楷力,太壓抑了喊式。”

let animal = { name: "animal" };

function eat(animal) {
    console.log(animal.name + " is eating");
}
eat(animal); // animal is eating

哦萧朝!Java 小王子恍然大悟岔留,原來 JavaScript 里的方法根本不用強制放在對象中去聲明,在這里函數已經翻身做主人检柬,成為了一等公民献联,再也不用困在對象的牢籠中,聲明后就可以直接使用何址。
“也就是說里逆,貓狗都可以直接拿來調用咯?”

let dog = { name: "dog" };
let cat = { name: "cat" };

eat(dog); // dog is eating
eat(cat); // cat is eating

函數式“封裝”

“是的呢~”小萊的臉上還是一樣的笑容用爪。
這樣的話原押,繼承和多態(tài)就變得毫無用武之地。函數直接操作的是數據偎血,數據不同诸衔,結果自然就不同,好似“多態(tài)”的體現颇玷,而且由于函數成了通用的東西笨农,無需繼承大家都可以使用,如有需要“重寫”帖渠,就干脆再寫一個函數就行了谒亦。而且 JavaSript 是動態(tài)類型,根本不需要再抽象出來一個“接口”來統一描述某種抽象。
“嗯... ”小王子總覺得哪里不對诊霹,好像少了點什么羞延,但又說不上來∑⒒梗“這是不是太自由了點... eat 本來只能是 animal 才能使用伴箩,現在任何東西都能用。這根本沒有封裝氨陕嗤谚!”
“是的呢~ 只要有 name 都可以用哦~這樣不是更好么?不過說到封裝怔蚌,我們的封裝可更厲害哦~”

function createAnimal(name) {
    let animal = {};
    animal.name = name;
    return animal;
}
// 或者直接
function createAnimal(name) {
    return { name: name };
}
eat(createAnimal("human")); // human is eating

更奇怪的封裝

沒錯巩步,封裝說到底是為了屏蔽細節(jié)實現,防止外界干擾桦踊。這么一來椅野,外界就不需要了解 eat 和 creatAnimal 的實現原理。小王子很是吃驚籍胯,但不得不承認這是一種有效的辦法竟闪。
“嗯~而且不僅可以封裝一些數據,還可以對函數進行封裝呢~”還沒等小王子緩過神兒杖狼,輕快的聲音又把他拉回現實炼蛤。“我們函數式教派里面叫它閉包蝶涩±砼螅”

function generateEatFunction(description) {
    function eat(animal) {
        console.log(animal.name + description);
    }
    return eat;
}

// 或者直接
function generateEatFunction(description) {
    return function(animal) {
        console.log(animal.name + description);
    }
}

let eatZH_CN = generateEatFunction(" 在吃東西~");
let xiaolai = createAnimal("小萊");

eatZH_CN(xiaolai); //小萊 在吃東西~

“啊绿聘?嗽上!”這次小王子徹底呆住了,信息量太大熄攘,他沒有想到函數還可以這么使用炸裆,竟然直接作為返回值返回,還可以“封裝”一些值進去鲜屏。
看到呆住的小王子,小萊解釋了起來国拇,“嘿嘿洛史,第一次見到的人都是這樣子,沒事酱吝,習慣了就好也殖。在我們函數式里面呢,函數中可以嵌套函數,內層的函數經常需要引用外層函數中的一些值忆嗜,而且可以把這個內層函數作為返回值呢~我肯定希望這個函數引用的外層值可以繼續(xù)使用啊己儒,這樣多方便啊。所以 JavaScript 就對其進行了處理捆毫,如果返回的函數被引用闪湾,JavaScript 就會同時保留這個函數所引用的東西,并不會回收它們(比如這里的 description)绩卤。你們面向對象的人其實也經常在方法中聲明局部變量是吧途样,但是你們并不會把一個函數返回出去,自然也就不會考慮方法執(zhí)行完畢之后要保持哪些局部變量濒憋,直接回收掉就好了何暇。”
“哦凛驮,這樣啊...”小王子還是一臉似懂非懂的樣子裆站。

“來,我們做一下分解動作黔夭,首先 description 在 generateEatFunction 內部是一個局部量宏胯。”

function generateEatFunction(description) {
    // description == " 在吃東西~"
    ...
}

“然后內層的函數使用了這個局部量纠修。此時一切都沒有問題胳嘲。”

function generateEatFunction(description) {
    function eat(animal) {
        // 這里引用了 description
        console.log(animal.name + description);
        // 相當于
        // console.log(animal.name + " 在吃東西~");
    }
    ...
}

“現在精彩的地方來了扣草,我把這個函數返回了出去~當然我不希望這個局部變量被回收了牛,我們依然希望它符合我的預期想法〕矫睿”

function generateEatFunction(description) {
    function eat(animal) {
        // 這里引用了 description
        console.log(animal.name + description);
        // 相當于
        // console.log(animal.name + " 在吃東西~");
    }
    return eat;
    // 希望 eat 的行為可以像這樣:
    // function eat(animal) {
    //     console.log(animal.name + " 在吃東西~");
    // }

}

let eatZH_CN = generateEatFunction(" 在吃東西~");

// 謝天謝地 JavaScrpit 的確沒有回收掉那個局部量鹰祸。
// 效果如同下面這樣:
// eatZH_CN = function eat(animal) { console.log(animal.name + " 在吃東西~"); }
// eatZH_CN 成功指向了我們生成的函數。
// 接下來就是正常的調用啦~

eatZH_CN(xiaolai); //小萊 在吃東西~

邁向高階

“嘿嘿密浑,還不止這樣呢~再給你看個東西~”小萊的話匣子一打開就停不下來蛙婴,由不得小王子發(fā)呆,自顧自的繼續(xù)介紹起來尔破〗滞迹“函數還可以作為參數傳呢~ 這些都叫高階函數~”

function each(list, fun) {
    for(let i = 0; i < list.length; i++){
        console.log(fun(list[i]));
    }
}

let animals = [dog, cat, xiaolai];

each(animals, eat);
// dog is eating
// cat is eating
// 小萊 is eating
// 

each(animals, eatZH_CN);
// dog 在吃東西~
// cat 在吃東西~
// 小萊 在吃東西~

“哇!傳遞進來的函數竟然真的就可以直接把它當作函數來使用懒构!這太神奇了餐济!”
“當然這里的 each 函數還不夠函數式,其實可以用遞歸實現啦~畢竟函數式里面不提倡用數組下標來做遍歷胆剧,但是到了 ES6 才有尾遞歸優(yōu)化絮姆,所以... ”小萊還在說著......


未來

“咳咳,小萊你夠了「菝酰客人都被你嚇到了蚁阳。”這時鸽照,在旁邊默默看著的大主教說話了螺捐。
小王子還在震驚之中,不過畢竟是皇族移宅,閱歷豐富归粉,還是悟出了一點門道,“我大概明白了一點漏峰,由于 JavaScript 是動態(tài)類型糠悼,其實無論是函數還是對象,在這里都可以做為一個值來傳遞浅乔。函數式里面偏向對值直接進行處理倔喂,通過對這些值的傳遞和組合,就可以組裝實現更高級的功能靖苇。上面的那個 each 方法也展現出來另一種“多態(tài)”的體現席噩。”
“不錯不錯贤壁,我看你這位朋友的來頭可不一般啊悼枢,新加入的信徒大多都經過漫長的適應期才能理解,他卻立即悟出這些道理來脾拆÷鳎”大主教對小王子贊賞有加,或許以他的智慧已經識破了小王子的身份名船。
“不不不绰上,還是因為小萊妹妹講的好啊∏眨”小王子臉紅的說道蜈块。
“這還不是多虧了我們的原型才能自由靈活的實現各種編程范式么∶陨龋”眼鏡大哥也參合了起來百揭。
“哈哈哈,你又在自夸了蜓席⌒啪”
“來,說了這么多 eat瓮床,不說了,吃菜吃菜~”

看來編程世界上還有這么多種形態(tài),小王子下次要去哪里隘庄,又會見識到怎樣的東西呢踢步?或許也能給他的 Java 帝國帶回一些新鮮的血液?


登場人物名:
小萊 == lambda

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末丑掺,一起剝皮案震驚了整個濱河市获印,隨后出現的幾起案子,更是在濱河造成了極大的恐慌街州,老刑警劉巖兼丰,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異唆缴,居然都是意外死亡鳍征,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門面徽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來艳丛,“玉大人,你說我怎么就攤上這事趟紊〉” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵霎匈,是天一觀的道長戴差。 經常有香客問我,道長铛嘱,這世上最難降的妖魔是什么暖释? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮弄痹,結果婚禮上饭入,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好痘儡,可當我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布淘衙。 她就那樣靜靜地躺著,像睡著了一般乾忱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上历极,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天窄瘟,我揣著相機與錄音,去河邊找鬼趟卸。 笑死蹄葱,一個胖子當著我的面吹牛氏义,可吹牛的內容都是我干的。 我是一名探鬼主播图云,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼惯悠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了竣况?” 一聲冷哼從身側響起克婶,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎丹泉,沒想到半個月后情萤,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡摹恨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年筋岛,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片睬塌。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡泉蝌,死狀恐怖,靈堂內的尸體忽然破棺而出揩晴,到底是詐尸還是另有隱情勋陪,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布硫兰,位于F島的核電站诅愚,受9級特大地震影響,放射性物質發(fā)生泄漏劫映。R本人自食惡果不足惜违孝,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望泳赋。 院中可真熱鬧雌桑,春花似錦、人聲如沸祖今。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽千诬。三九已至耍目,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間徐绑,已是汗流浹背邪驮。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留傲茄,地道東北人毅访。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓沮榜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親喻粹。 傳聞我的和親對象是個殘疾皇子敞映,可洞房花燭夜當晚...
    茶點故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內容

  • 'A' 新增 'D' 刪除 'M' 修改 'R' 替代 'C' 沖突 'I' 忽略 '?' 未受控 '!' 丟失,...
    丶逝水流年閱讀 2,168評論 0 5
  • 枯死的樹 拉大鋸扯大鋸 伐回 劈成小段四半 木頭 堆在墻角似山 木頭挨著木頭 不說話 不會動
    夏霖捷閱讀 135評論 0 0
  • 回了趟家磷斧,在家?guī)Я藥滋旌⒆樱戳它c書捷犹,就這樣弛饭。連向來懶惰的xb都忍不住發(fā)來消息催問我寫摘要的事,咳萍歉,其實懶懶的真好...
    潔瑜GW閱讀 165評論 0 0
  • 人總會在失敗中不斷成長侣颂。一次失敗算不了什么,因為你肯定不會再在同一個地方失敗枪孩。而我憔晒,卻不免嘲笑自己。是的蔑舞,我...
    夢見我夢見你夢她i閱讀 379評論 3 2
  • 869560023876017
    Nightmare夢_2654閱讀 169評論 0 0