Call、Apply与Bind的区别:事件绑定中的行为差异解析
先看你的代码场景:给按钮加点击事件时,用bind能让每次点击都触发counter.count递增,但换成call或apply只会在绑定事件那一刻执行一次,之后点击毫无反应,核心原因是这三个方法的执行时机和返回值完全不同:
1. bind的作用逻辑
bind(counter)会返回一个全新的、已经绑定好this指向的函数,这个函数不会立即执行,而是作为事件回调传给addEventListener。每次按钮被点击时,浏览器就会调用这个绑定好的函数,此时函数内部的this已经被固定为counter,所以每次点击都会执行this.count++,实现累加效果。
底层来说,bind的本质是创建了一个闭包,它把原函数(incrementCounter)和指定的this(counter)保存起来,当新函数被调用时,就通过闭包访问这些保存的值,确保执行原函数时this不会被事件触发的默认上下文(这里是按钮元素)覆盖。
2. call/apply的问题所在
call和apply的作用是立即执行目标函数,同时强制指定函数执行时的this。如果你写counter.incrementCounter.call(counter),这行代码在执行到的时候就会立刻调用incrementCounter,此时this是counter,count会加1,但这个表达式的返回值是incrementCounter的返回值(这里是undefined)。
也就是说,你传给addEventListener的不是一个待执行的函数,而是undefined,所以之后点击按钮时,根本没有对应的回调函数可以执行,自然只会在绑定事件时执行一次,之后点击无反应。
简单总结
bind:返回绑定好this的待执行函数,适合作为回调使用call/apply:立即执行函数并指定this,适合直接调用函数的场景
内容的提问来源于stack exchange,提问作者Hardik

