JavaScript中HTMLElement.onclick调用时访问对象属性的问题
解决原型方法作为onclick事件时的this指向问题
这个问题我之前也碰到过,核心原因是DOM事件处理函数触发时,this默认会绑定到触发事件的HTML元素上,不管这个函数是来自实例还是原型。所以当你把原型上的whoAreYou直接赋值给onclick时,函数里的this就变成了按钮元素,自然拿不到实例的name属性。
先重现一下你的问题代码,方便大家理解:
<button id="testBtn">点击测试</button> <script> function Somebody(name) { this.name = name; } // 方法放在原型上,希望继承复用 Somebody.prototype.whoAreYou = function() { console.log(`I am ${this.name}`); // 点击后输出"I am undefined",因为this是按钮元素 }; const gary = new Somebody('Gary'); document.getElementById('testBtn').onclick = gary.whoAreYou; </script>
下面给你两种既保留原型继承特性,又能正确访问实例name的解决方案:
方案1:用bind()永久绑定实例到方法
bind()方法会创建一个新函数,强制把函数的this绑定到你传入的对象上,不管后续怎么调用这个函数,this都不会变。
修改事件绑定的代码即可:
<button id="testBtn">点击测试</button> <script> function Somebody(name) { this.name = name; } Somebody.prototype.whoAreYou = function() { console.log(`I am ${this.name}`); // 现在this是gary实例,输出"I am Gary" }; const gary = new Somebody('Gary'); // 把whoAreYou的this绑定到gary实例 document.getElementById('testBtn').onclick = gary.whoAreYou.bind(gary); </script>
这种方式完美保留了原型方法的继承性——如果后续你创建Somebody的子类,子类可以直接重写或复用whoAreYou方法,完全不影响。
方案2:用箭头函数包装事件处理逻辑
箭头函数不会绑定自己的this,它的this会继承自外层作用域。你可以用箭头函数作为事件处理函数,在里面调用实例的原型方法:
<button id="testBtn">点击测试</button> <script> function Somebody(name) { this.name = name; } Somebody.prototype.whoAreYou = function() { console.log(`I am ${this.name}`); }; const gary = new Somebody('Gary'); // 箭头函数的this继承自当前外层作用域(这里是全局作用域的gary实例) document.getElementById('testBtn').onclick = () => gary.whoAreYou(); </script>
如果是在构造函数内部绑定事件,箭头函数的this会直接指向当前实例,更方便:
function Somebody(name, btnId) { this.name = name; // 这里的this就是当前Somebody实例 document.getElementById(btnId).onclick = () => { this.whoAreYou(); }; }
这种方式同样不影响原型方法的继承,子类重写whoAreYou后,实例调用的就是子类的方法。
总结
优先推荐bind()方案,它更贴合函数绑定的语义,而且不会额外创建多余的函数嵌套。箭头函数方案则更简洁,适合快速实现。两种方案都能满足你“保留原型继承性”的需求。
内容的提问来源于stack exchange,提问作者Powercoder
相关产品推荐
相关产品推荐

