自定义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未定义。
问题原因
- 原型方法误用箭头函数:箭头函数没有自身的
this绑定,会继承外层作用域的this,导致原型方法内的this无法指向__的实例对象,自然访问不到实例上的属性。 - 未全局暴露
__函数:虽然本次错误主要由箭头函数导致,但要在外部正常调用__,需要将其挂载到全局作用域。
修正后的可用代码
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,提问作者Војин Петровић
相关产品推荐
相关产品推荐

