当this指向jQuery对象时,如何正确引用类自身实例
jQuery事件绑定后类方法this指向错误的解决方法
问题背景
我正在为多配置页面的应用开发模块化元素处理器,定义了LengthElement类处理英尺/英寸输入,统一以英寸存储值并同步显示。通过config数组管理不同配置的元素ID,避免重复编写ID。但绑定input事件后,InputVal方法中的this指向jQuery对象而非类实例,导致无法访问类的属性和方法。目前无法更换jQuery框架,需要解决this指向问题,同时保留现有模块化逻辑。
原类代码如下:
class LengthElement { inches; //Value of the Two Elements in Inches foot; //String of the Foot Element inch; //String of the Inch Element div7; //Flag to determine if change needs to be Divisible by 7 OnChange; //Function specific to the instance to be called whenever the input changes constructor(i, cfg, abrv, oC) { this.inches = i; if (cfg.foot == 'input') { this.foot = '#' + abrv + '-' + cfg.name + '-ft-input'; $(this.foot).on('input', this.InputVal); } else { this.foot = '#' + abrv + '-' + cfg.name + '-ft-box'; } if (cfg.inch == 'input') { this.inch = '#' + abrv + '-' + cfg.name + '-in-input'; $(this.inch).on('input', this.InputVal); } else { this.inch = '#' + abrv + '-' + cfg.name + '-in-box'; } this.div7 = cfg.div7; this.OnChange = oC; } GetFeet(i) { return Math.floor(i / 12); } GetInches(i) { return i % 12; } GetDiv7(i) { if (i % 7 > 5) { return i + (7 - (i % 7)); } else { return i - (i % 7); } } GetVal() { return this.inches; } UpdateVal(i) { if (this.div7) { this.inches = this.GetDiv7(i); } else { this.inches = i; } $(this.foot).val(this.GetFeet(this.inches)); $(this.inch).val(this.GetInches(this.inches)); } InputVal() { var newInches = ($(this.foot).val() * 12) + $(this.inch).val(); var change = newInches - this.inches; if (this.div7) { if (change > 0) { newInches = this.inches + ((Math.floor(change / 7) * 7) + 7); } else if (change < 0) { newInches = this.inches - ((Math.floor(change / 7) * 7) + 7); } else { newInches = this.GetDiv7(newInches); } } this.UpdateVal(newInches); this.OnChange(); } }
可行解决方案
方案1:用bind()绑定类实例的this
修改构造函数中的事件绑定代码,给InputVal方法绑定类实例的this,确保方法内部的this始终指向类实例:
// 英尺输入框绑定修改 if (cfg.foot == 'input') { this.foot = '#' + abrv + '-' + cfg.name + '-ft-input'; $(this.foot).on('input', this.InputVal.bind(this)); } // 英寸输入框绑定修改 if (cfg.inch == 'input') { this.inch = '#' + abrv + '-' + cfg.name + '-in-input'; $(this.inch).on('input', this.InputVal.bind(this)); }
bind(this)会创建一个新函数,调用时强制把this指向当前类实例,这样InputVal里就能正常访问this.inches、this.UpdateVal()等类成员了。
方案2:用箭头函数包裹事件处理逻辑
箭头函数的this继承自外层作用域(这里就是类实例),所以可以用箭头函数作为事件处理函数,内部直接调用this.InputVal():
// 英尺输入框绑定修改 if (cfg.foot == 'input') { this.foot = '#' + abrv + '-' + cfg.name + '-ft-input'; $(this.foot).on('input', () => this.InputVal()); } // 英寸输入框绑定修改 if (cfg.inch == 'input') { this.inch = '#' + abrv + '-' + cfg.name + '-in-input'; $(this.inch).on('input', () => this.InputVal()); }
这种写法简洁直观,不需要额外处理this的指向问题,适合现代浏览器环境。
方案3:在构造函数中保存类实例引用
在构造函数里把this存到一个变量(比如self),然后用普通函数作为事件处理函数,内部用self代替this访问类成员:
constructor(i, cfg, abrv, oC) { this.inches = i; const self = this; // 保存类实例的引用 if (cfg.foot == 'input') { this.foot = '#' + abrv + '-' + cfg.name + '-ft-input'; $(this.foot).on('input', function() { self.InputVal(); // 通过self调用方法,确保指向类实例 }); } if (cfg.inch == 'input') { this.inch = '#' + abrv + '-' + cfg.name + '-in-input'; $(this.inch).on('input', function() { self.InputVal(); }); } // ... 构造函数其他代码不变 }
这种方法兼容性最好,哪怕是旧版本浏览器也能正常运行,适合需要兼容低版本环境的场景。
内容的提问来源于stack exchange,提问作者mshaw
相关产品推荐
相关产品推荐

