JavaScript中处理this指针与自定义参数的最优方案及事件监听困惑
我太懂这种在类方法里写事件监听时,this突然“变味”的困惑了!你的核心问题是事件回调函数里的this默认指向触发事件的DOM元素(也就是那个删除按钮),但你大概率想在回调里同时访问Sample实例的attra、attrb这些属性,还有按钮本身,对吧?
先把你的原始代码补全并修正细节(比如补上变量声明、修正addEventListener的拼写),方便对照:
Sample.prototype.myfunc = function my_func() { this.attra = someValue; this.attrb = someValueb; // 补上const/let避免全局变量 const tmpDelNode = this.doc.createElement('span'); tmpDelNode.innerHTML = '<span class="del">X</span>'; this.newAttachmentContainer.appendChild(tmpDelNode.firstChild); const delbtn = this.doc.querySelector('.del'); // 这里的回调里this会指向delbtn,而非Sample实例 delbtn.addEventListener('click', function() { console.log(this); // 输出的是<span class="del">X</span>,不是Sample实例 // 想访问this.attra?这里根本拿不到! }); };
下面给你三种常用的解决思路,按需选择:
方法1:用箭头函数继承外层this
箭头函数不会绑定自己的this,会直接沿用父作用域(也就是myfunc方法里的this,即Sample实例)的this。如果要访问按钮本身,用event.target即可:
Sample.prototype.myfunc = function my_func() { this.attra = someValue; this.attrb = someValueb; const tmpDelNode = this.doc.createElement('span'); tmpDelNode.innerHTML = '<span class="del">X</span>'; this.newAttachmentContainer.appendChild(tmpDelNode.firstChild); const delbtn = this.doc.querySelector('.del'); delbtn.addEventListener('click', (event) => { console.log(this.attra); // 完美访问Sample实例的属性! console.log(event.target); // 拿到触发事件的删除按钮 }); };
方法2:用bind()把this绑定到实例
如果习惯用普通函数写回调,可以用bind()强制把回调的this绑定到Sample实例,同样用event.target访问按钮:
Sample.prototype.myfunc = function my_func() { this.attra = someValue; this.attrb = someValueb; const tmpDelNode = this.doc.createElement('span'); tmpDelNode.innerHTML = '<span class="del">X</span>'; this.newAttachmentContainer.appendChild(tmpDelNode.firstChild); const delbtn = this.doc.querySelector('.del'); // 先定义回调函数 const handleDelete = function(event) { console.log(this.attra); // this是Sample实例 console.log(event.target); // 按钮元素 }; // 绑定this后再添加监听 delbtn.addEventListener('click', handleDelete.bind(this)); };
方法3:保存外层this到变量(传统写法)
在myfunc里把实例的this存到一个变量(比如self或that),然后在回调里用这个变量访问实例,此时普通函数里的this还是指向按钮:
Sample.prototype.myfunc = function my_func() { const self = this; // 把Sample实例的this存起来 this.attra = someValue; this.attrb = someValueb; const tmpDelNode = this.doc.createElement('span'); tmpDelNode.innerHTML = '<span class="del">X</span>'; this.newAttachmentContainer.appendChild(tmpDelNode.firstChild); const delbtn = this.doc.querySelector('.del'); delbtn.addEventListener('click', function(event) { console.log(self.attra); // 用self访问实例属性 console.log(this); // 这里的this还是删除按钮 }); };
额外小提示
如果页面上会有多个.del按钮,querySelector只会返回第一个匹配的元素,建议直接给刚创建的按钮加监听,不用去DOM里查找:
// 直接获取刚创建的删除按钮,省去querySelector的步骤 const delbtn = tmpDelNode.firstChild; delbtn.addEventListener('click', ...);
内容的提问来源于stack exchange,提问作者Suganya Selvarajan
相关产品推荐
相关产品推荐

