为何需绑定通过同一对象调用的被遮蔽函数?
为什么直接引用Array.prototype.pop会触发this绑定错误?
先来看你遇到的代码场景:
Array.prototype.hook_pop = function(callback) { // 方式一:可行 var base_pop = this.pop.bind(this); // 方式二:不可行,报错 "Uncaught TypeError: Cannot convert undefined or null to object" // var base_pop = this.pop; this.pop = function() { var ret = base_pop(); callback(ret, this); return ret; } }
核心原因:函数的this是调用时决定的,不是定义时
你之前的理解有个小偏差:“除非显式绑定,否则this应指向调用方法的对象”——这句话没错,但前提是你是通过原对象调用方法。而当你把this.pop赋值给base_pop变量时,本质上是把Array.prototype.pop这个函数本身抽离出来了,和原数组实例断开了关联。
当你后续调用base_pop()时,这是一个独立函数调用,此时的this在非严格模式下会绑定到全局对象(浏览器里是window),严格模式下则是undefined。而原生的pop方法要求this必须是一个数组对象,否则就会抛出“无法将undefined/null转为对象”的错误——因为它内部要操作数组的length属性、访问元素,这些都依赖this是合法的数组。
为什么bind就可行?
bind方法会创建一个新的绑定函数,这个函数的this被永久固定为你传入的参数(也就是当前的数组实例)。不管你后续怎么调用这个绑定后的函数,它内部的this都不会变,始终指向原数组。所以调用base_pop()时,pop方法能正常拿到正确的this,自然就能正常执行。
举个更直观的例子辅助理解
const arr = [1,2,3]; // 直接取方法,和原对象断开 const rawPop = arr.pop; rawPop(); // 报错,此时this不是arr // 绑定this后 const boundPop = arr.pop.bind(arr); boundPop(); // 正常执行,弹出3
总结
当你需要保存一个对象的方法并在后续独立调用时,如果这个方法的逻辑依赖原对象的this,必须通过bind显式绑定this,否则会丢失原对象的上下文,导致方法无法正常工作。
内容的提问来源于stack exchange,提问作者user81993
相关产品推荐
相关产品推荐

