如何创建JavaScript函数式‘类’,实现方法内外可访问?
更优的实现方案:兼顾内部调用与外部访问
你遇到的问题其实很常见——既要让核心方法能在构造函数内部的嵌套回调里方便调用,又要能从外部实例访问。下面给你几种比现有写法更优雅的解决方案:
方案1:ES6箭头函数处理事件回调(推荐现代环境)
箭头函数不会绑定自己的this,它会继承外层作用域的this(也就是构造函数实例的this),这样在事件监听的回调里可以直接用this.keyMethod(),完全不需要bind:
const testFunction = function() { // 把方法挂载到实例上,支持外部访问 this.keyMethod = function() { console.log('ya got me'); }; // 箭头函数继承外层this,直接调用实例方法 document.getElementById('test').addEventListener('click', (e) => { this.keyMethod(); // 这里的e依然正常工作,不会影响元素定位 }); // 内部直接调用 this.keyMethod(); }; const myTest = new testFunction(); myTest.keyMethod(); // 外部正常访问
这个方案的优势:
- 不需要额外的变量存储
this,代码简洁 - 事件回调里的
e参数不受影响,完全不干扰元素定位 - 同时满足内部嵌套函数和外部实例的访问需求
方案2:存储this为变量(兼容ES5及更早环境)
如果需要兼容旧环境,没法用箭头函数,可以在构造函数开头把this存为一个变量(比如self或that),之后所有嵌套函数里都用这个变量调用方法:
var testFunction = function() { var self = this; // 存储实例的this引用 this.keyMethod = function() { console.log('ya got me'); }; document.getElementById('test').addEventListener('click', function(e) { self.keyMethod(); // 用存储的self调用,避免this指向问题 }); this.keyMethod(); }; var myTest = new testFunction(); myTest.keyMethod(); // 外部正常访问
这个方案的优势:
- 兼容所有JS环境,没有语法版本限制
- 嵌套函数里的
this依然可以正常指向事件目标(如果需要的话),而self稳定指向实例
方案3:ES6类语法(最清晰的现代写法)
如果你的项目已经使用ES6+,用类语法会让代码结构更清晰,类的实例方法天然支持外部访问,结合箭头函数还能避免回调里的this问题:
class TestFunction { constructor() { // 类的方法默认挂载到实例上 document.getElementById('test').addEventListener('click', (e) => { this.keyMethod(); }); this.keyMethod(); } keyMethod() { console.log('ya got me'); } } const myTest = new TestFunction(); myTest.keyMethod(); // 外部正常访问
甚至可以把方法定义为类字段的箭头函数(这样永远绑定实例this,不用在回调里纠结):
class TestFunction { // 箭头函数类字段,this永久绑定实例 keyMethod = () => { console.log('ya got me'); }; constructor() { document.getElementById('test').addEventListener('click', this.keyMethod); this.keyMethod(); } }
为什么你的两种写法有问题?
- 第一种写法里的
keyMethod是构造函数内部的普通变量,不是实例的属性,所以外部实例访问不到 - 第二种写法里的事件回调是普通函数,
this指向事件目标(按钮元素),所以直接调用keyMethod()会报错,必须bind(this)或者用箭头函数修正this指向
内容的提问来源于stack exchange,提问作者Rolf Herbert
相关产品推荐
相关产品推荐

