从removeEventListener的应用失败案例看bind()函数的本质

知其然

首先先来看下面一个例子(文字部分为源码,亦有方便读者查看)

  

    result:      
  aim btn  fun1 add  fun1 remove


源码截图

点击fun1 add按钮,添加按钮事件后,点击aim按钮可以成功显示triggered!success.然而点击fun1 remove按钮尝试移除事件后,再次点击aim按钮,却仍然显示出triggered!success.

可见,虽然是同名函数,并且绑定了相同的作用域,然而移除方法并没有生效.这是为什么呢?

知其所以然

一书中,是这么描述bind方法的:

ECMAScript 5 还定义了一个方法: bind().这个方法会创建一个函数的示例,其this值会被绑定到传给bind()函数的值.(由于时间仓促找不到对应在线文献,以上字符均为手打,心疼笔者的请点个赞)

这里的描述有个关键字:创建.与call/apply不同,bind属性函数并不是针对函数对象的使用,而是创建一个新的函数对象.

众所周知,函数名其实是函数对象的指针,func.bind(obj)这个语句中,func是指向的是同一个函数对象,而整个语句确实一个创建型的函数,bind()方法执行后,将会创建一个新的函数对象,并绑定对应的作用域,在增加事件跟移除事件的时候虽然调用的是相同语句,然而两者返回的却是不同的函数引用,自然不能正确的移除dom的click事件.

原因找到了.解决之前问题的办法自然而然就浮现出来了.使用func.bind(obj)的时候可以将返回的函数引用在外部存储起来,在移除事件的时候使用即可,改良后的代码如下:


改良后的add与remove函数

改良后移除事件后再点击aim按钮便不会显示triggered!success.了

本文中的所有代码与实际的页面展示均可以在笔者codepen上看到与体验:https://codepen.io/pandaboxer/pen/GRozxyJ

更新不易,点个赞再走吧靓仔

你可能感兴趣的:(从removeEventListener的应用失败案例看bind()函数的本质)