JavaScript为NodeList添加事件时bind用法的两点技术疑问
问题背景
有实现方案演示了为NodeList批量绑定事件的写法,对应代码如下:
var unboundForEach = Array.prototype.forEach, forEach = Function.prototype.call.bind(unboundForEach); forEach(document.querySelectorAll('.klasses'), function (el) { el.addEventListener('click', someFunction); });
学习该实现时常见两个疑问,解答如下:
疑问解答
1. 为什么需要对unboundForEach执行bind绑定操作?
Array.prototype.forEach是数组原型上的实例方法,设计要求必须以数组/类数组对象作为执行上下文(即方法内部的this)才能正常运行。
当我们把Array.prototype.forEach直接赋值给变量unboundForEach时,方法脱离了原原型的调用环境,直接调用unboundForEach()时,内部this在非严格模式下会指向全局对象,严格模式下为undefined,会直接抛出类型错误。
这里的bind操作本质是提前固定方法的执行上下文逻辑,让生成的新函数可以自动把传入的集合作为forEach的执行上下文,不需要每次手动指定上下文。
2. 为什么此处使用Function.prototype.call.bind,而非直接使用Function.prototype.bind?
两种绑定方式的定位完全不同:
- 如果直接用
unboundForEach.bind(待遍历集合),本质是把forEach的执行上下文提前固定死为某一个特定集合,每次遍历不同的NodeList/类数组都要重新做一次绑定,根本没法做成通用的遍历工具函数。 - 用
Function.prototype.call.bind(unboundForEach)生成的是一个通用遍历函数,逻辑等价于下面的手写实现:
function forEach(context, callback, thisArg) { return unboundForEach.call(context, callback, thisArg); }
这个新函数可以接收任意数组/类数组作为第一个参数(自动作为forEach的执行上下文),后续参数直接透传给原生forEach,调用方式和原生数组的arr.forEach(cb)逻辑对齐,不用每次写冗长的Array.prototype.forEach.call()写法,通用性和简洁度都更高。
内容的提问来源于stack exchange,提问作者user159
相关产品推荐
相关产品推荐

