JavaScript中HTML按钮onclick调用类方法失效问题排查
理解JS中this的指向问题及解决方法
嘿,刚从Python转JS的时候我也被这个this指向坑过!咱们先把问题的核心原理搞清楚,再看怎么解决。
为什么会出现这个问题?
Python里类的方法默认会把实例绑定到第一个参数(也就是你熟悉的self),所以不管你怎么调用方法,self都指向类实例。但JS里的this是调用时动态绑定的,不是定义时固定的:
- 当你直接调用
i.test()时,this指向的是Test的实例i,所以能正常读取this.name; - 当按钮的
onclick触发时,this指向的是按钮这个DOM元素本身(因为事件触发时,浏览器会把事件源设为this),而按钮元素没有name属性,所以弹窗显示为空。
几种解决方法
方法1:使用箭头函数绑定外层作用域的this
箭头函数不会创建自己的this,它会继承外层作用域的this。在testwindow方法里,外层的this就是Test的实例,所以可以这样写:
testwindow(){ var tmp = document.createElement('button'); tmp.id = 'idtest'; tmp.className = 'test'; // 用箭头函数包裹,让test里的this指向实例 tmp.onclick = () => this.test(); tmp.innerHTML = 'Klick mich'; document.body.appendChild(tmp); }
方法2:使用bind()手动绑定this
bind()方法会返回一个新函数,这个函数的this会被固定绑定到你传入的对象上。我们可以把test方法的this绑定到Test实例:
testwindow(){ var tmp = document.createElement('button'); tmp.id = 'idtest'; tmp.className = 'test'; // 绑定this为当前实例 tmp.onclick = this.test.bind(this); tmp.innerHTML = 'Klick mich'; document.body.appendChild(tmp); }
方法3:在构造函数中提前绑定方法
如果这个方法会被多次用作事件回调,你可以在构造函数里就把test方法的this绑定好,后面直接用就行:
class Test{ constructor(){ this.name = 'heinz'; // 提前绑定this到实例 this.test = this.test.bind(this); } testwindow(){ var tmp = document.createElement('button'); tmp.id = 'idtest'; tmp.className = 'test'; // 现在直接赋值就行,this已经绑定好了 tmp.onclick = this.test; tmp.innerHTML = 'Klick mich'; document.body.appendChild(tmp); } test(){ alert(this.name); } }
额外提醒
JS的this规则确实和Python的self差异很大,记住几个核心场景:
- 普通函数调用:
this指向全局对象(浏览器里是window,严格模式下是undefined); - 对象方法调用:
this指向调用方法的对象; - 事件回调:
this指向触发事件的DOM元素; - 箭头函数:
this继承自外层作用域的this。
内容的提问来源于stack exchange,提问作者Michael Beckmann
相关产品推荐
相关产品推荐

