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

自定义JS类原型方法用箭头函数致this未定义的问题解决

自定义类库替代jQuery时的this指向问题

我正在学习原生JavaScript并构建自有类库,计划弃用jQuery,于是创建了类似jQuery $的__函数,并编写了_addClass原型方法用于为DOM元素添加类。

原始代码

JavaScript代码

(() => {
    function __(arg) {
        if (!(this instanceof __))
            return new __(arg);
        this.element = null;
        this.elements = null;
        this.singleElement = false;
        switch (arg.substring(0, 1)) {
            case ".":
                this.elements = document.getElementsByClassName(arg.substring(1));
                break;
            case "#":
                this.element = document.getElementById(arg.substring(1));
                this.singleElement = true;
                break;
            case "&":
                this.elements = document.getElementsByName(arg.substring(1));
                break;
            default:
                this.elements = document.querySelectorAll(arg);
                break;
        }
        return this;
    }

    __.prototype._addClass = (a) => {
        if (this.singleElement) {
            this.element.classList.add(a);
            return this.element;
        } else {
            this.elements.forEach((element) => element.classList.add(a));
            return this.elements;
        }
    }

    document.getElementById("btn").addEventListener("click", () => {
        __("#test")._addClass("new-class-style");
    })
})();

HTML代码

<div id="test">Div content</div>
<button id="btn">Button</button>

运行错误

Uncaught TypeError: Cannot read properties of undefined (reading 'classList')

错误指向this.element、this.elements或this.singleElement未定义。

问题原因

  1. 原型方法误用箭头函数:箭头函数没有自身的this绑定,会继承外层作用域的this,导致原型方法内的this无法指向__的实例对象,自然访问不到实例上的属性。
  2. 未全局暴露__函数:虽然本次错误主要由箭头函数导致,但要在外部正常调用__,需要将其挂载到全局作用域。

修正后的可用代码

JavaScript代码

(() => {
    function __(selector) {
        if (!(this instanceof __))
        return new __(selector);
        this.elements = null;
        if (selector !== undefined) 
            this.elements = document.querySelectorAll(selector);
        return this;
    }

    __.prototype.addClass = function (...a) {
        this.elements.forEach((element) => {
            a.forEach((className) => element.classList.add(className));
        });
        return this;
    }
    __.prototype.removeClass = function (...a) {
        this.elements.forEach((element) => {
            a.forEach((className) => element.classList.remove(className));
    });
        return this;
    }
    __.prototype.html = function (a) {
        if (a === undefined) {
            let out = "";
            this.elements.forEach((element) => out = element.innerHTML);
            return out;
        }
        this.elements.forEach((element) => element.innerHTML = a);
        return this;
    }
    __.prototype.text = function (a) {
        if (a === undefined) {
            let out = "";
            this.elements.forEach((element) => out = element.innerText);
            return out;
        }
        this.elements.forEach((element) => element.innerText = a);
        return this;
    }
    __.prototype.on = function (type, callback) {
        this.elements.forEach((element) => {
            element.addEventListener(type, callback);
        });
        return this;
    }
    window.__ = __;
})();

__("#btn").on("click", () => {
    __("#test").addClass("some-class").text("Div content changed");
})

HTML代码

<div id="test">Div content</div>
<button id="btn">Button</button>

内容的提问来源于stack exchange,提问作者Војин Петровић

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 15:48:31