美文网首页
从removeEventListener的应用失败案例看bind

从removeEventListener的应用失败案例看bind

作者: 熊猫拳击手 | 来源:发表于2020-07-23 00:30 被阅读0次

知其然

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

<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>

源码截图

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

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

知其所以然

在<js高级程序设计>一书中,是这么描述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

      本文链接:https://www.haomeiwen.com/subject/zqnxlktx.html