從removeEventListener的應(yīng)用失敗案例看bind()函數(shù)的本質(zhì)

知其然

首先先來看下面一個(gè)例子(文字部分為源碼,亦有方便讀者查看)

<body>??<div>????<span>result:</span>????<span?id="result"></span>??</div>??<button?id="aim">aim?btn</button>??<button?onclick="addFunc1()">fun1?add</button>??<button?onclick="removeFunc1()">fun1?remove</button></body><script>??const?aim?=?document.getElementById('aim');??const?result?=?document.getElementById('result');??const?obj?=?{????content:?'success'??};??const?func?=?function()?{????result.innerText?=?'triggered!'?+?this.content;??};??const?removeFunc1?=?function()?{????result.innerText?=?'fun1?removed';????aim.removeEventListener('click',?func.bind(obj))??};??const?addFunc1?=?function()?{????result.innerText?=?'fun1?added';????aim.addEventListener('click',?func.bind(obj));??};</script>


源碼截圖

點(diǎn)擊fun1 add按鈕,添加按鈕事件后,點(diǎn)擊aim按鈕可以成功顯示triggered!success.然而點(diǎn)擊fun1 remove按鈕嘗試移除事件后,再次點(diǎn)擊aim按鈕,卻仍然顯示出triggered!success.

可見,雖然是同名函數(shù),并且綁定了相同的作用域,然而移除方法并沒有生效.這是為什么呢?

知其所以然

在<js高級(jí)程序設(shè)計(jì)>一書中,是這么描述bind方法的:

ECMAScript 5 還定義了一個(gè)方法: bind().這個(gè)方法會(huì)創(chuàng)建一個(gè)函數(shù)的示例,其this值會(huì)被綁定到傳給bind()函數(shù)的值.(由于時(shí)間倉促找不到對(duì)應(yīng)在線文獻(xiàn),以上字符均為手打,心疼筆者的請(qǐng)點(diǎn)個(gè)贊)

這里的描述有個(gè)關(guān)鍵字:創(chuàng)建.與call/apply不同,bind屬性函數(shù)并不是針對(duì)函數(shù)對(duì)象的使用,而是創(chuàng)建一個(gè)新的函數(shù)對(duì)象.

眾所周知,函數(shù)名其實(shí)是函數(shù)對(duì)象的指針,func.bind(obj)這個(gè)語句中,func是指向的是同一個(gè)函數(shù)對(duì)象,而整個(gè)語句確實(shí)一個(gè)創(chuàng)建型的函數(shù),bind()方法執(zhí)行后,將會(huì)創(chuàng)建一個(gè)新的函數(shù)對(duì)象,并綁定對(duì)應(yīng)的作用域,在增加事件跟移除事件的時(shí)候雖然調(diào)用的是相同語句,然而兩者返回的卻是不同的函數(shù)引用,自然不能正確的移除dom的click事件.

原因找到了.解決之前問題的辦法自然而然就浮現(xiàn)出來了.使用func.bind(obj)的時(shí)候可以將返回的函數(shù)引用在外部存儲(chǔ)起來,在移除事件的時(shí)候使用即可,改良后的代碼如下:


改良后的add與remove函數(shù)

改良后移除事件后再點(diǎn)擊aim按鈕便不會(huì)顯示triggered!success.了

本文中的所有代碼與實(shí)際的頁面展示均可以在筆者codepen上看到與體驗(yàn):https://codepen.io/pandaboxer/pen/GRozxyJ

更新不易,點(diǎn)個(gè)贊再走吧靚仔

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子早芭,更是在濱河造成了極大的恐慌幅慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,080評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件暑劝,死亡現(xiàn)場(chǎng)離奇詭異猾骡,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)印屁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來斩例,“玉大人雄人,你說我怎么就攤上這事。” “怎么了础钠?”我有些...
    開封第一講書人閱讀 157,630評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵恰力,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我旗吁,道長(zhǎng)踩萎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,554評(píng)論 1 284
  • 正文 為了忘掉前任很钓,我火速辦了婚禮香府,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘码倦。我一直安慰自己企孩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,662評(píng)論 6 386
  • 文/花漫 我一把揭開白布袁稽。 她就那樣靜靜地躺著勿璃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪推汽。 梳的紋絲不亂的頭發(fā)上补疑,一...
    開封第一講書人閱讀 49,856評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音民泵,去河邊找鬼癣丧。 笑死,一個(gè)胖子當(dāng)著我的面吹牛栈妆,可吹牛的內(nèi)容都是我干的胁编。 我是一名探鬼主播,決...
    沈念sama閱讀 39,014評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼鳞尔,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼嬉橙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起寥假,我...
    開封第一講書人閱讀 37,752評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤市框,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后糕韧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體枫振,經(jīng)...
    沈念sama閱讀 44,212評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,541評(píng)論 2 327
  • 正文 我和宋清朗相戀三年萤彩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了粪滤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,687評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡雀扶,死狀恐怖杖小,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤予权,帶...
    沈念sama閱讀 34,347評(píng)論 4 331
  • 正文 年R本政府宣布昂勉,位于F島的核電站,受9級(jí)特大地震影響扫腺,放射性物質(zhì)發(fā)生泄漏岗照。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,973評(píng)論 3 315
  • 文/蒙蒙 一斧账、第九天 我趴在偏房一處隱蔽的房頂上張望谴返。 院中可真熱鬧,春花似錦咧织、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蝙昙,卻和暖如春闪萄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背奇颠。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工败去, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人烈拒。 一個(gè)月前我還...
    沈念sama閱讀 46,406評(píng)論 2 360
  • 正文 我出身青樓圆裕,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親荆几。 傳聞我的和親對(duì)象是個(gè)殘疾皇子吓妆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,576評(píng)論 2 349