You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

当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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 17:35:25