JavaScript面试题:实现类A使实例调用时依次返回1、2(新实例重置)
实现可调用的类A实例,独立维护递增计数
我来帮你解决这个面试题的问题~首先咱们得先理清核心需求:你需要让new A()创建的实例本身能被当作函数调用,而且每个实例要独立维护自己的计数——第一次调用返回1,第二次返回2,新实例则重新从1开始计数。
先说说你原来代码的两个关键问题:
- 类的方法定义语法错误:class内部不能用
function(){}这种写法,正确的方法定义应该是methodName() {} - 核心问题:
new A()默认创建的是普通对象,普通对象不具备可调用能力(没有[[Call]]内部方法),所以直接调用a()会报错a is not a function
正确实现方案
我们可以利用闭包特性,在constructor里返回一个可调用的函数,让这个函数维护当前实例的独立计数,同时保证它是A的实例(符合类的语义):
class A { constructor() { // 闭包保存当前实例的计数,每个实例的count完全独立 let count = 1; // 创建可被调用的实例函数 const callableInstance = () => { return count++; }; // 让这个函数继承A的原型,保证它是A的实例(可选,但语义更完整) Object.setPrototypeOf(callableInstance, A.prototype); // 返回这个可调用函数作为最终实例 return callableInstance; } }
测试验证
var a = new A(); console.log(a()); // 输出 1 console.log(a()); // 输出 2 var b = new A(); console.log(b()); // 输出 1 console.log(b()); // 输出 2
原理说明
- 每次执行
new A()都会触发一次constructor,每个实例都会拥有自己独立的count变量(闭包特性保证了变量不会被外部干扰,也不会被其他实例共享) - 返回的
callableInstance是箭头函数,每次调用都会返回当前count值并完成自增 - 通过
Object.setPrototypeOf让返回的函数继承A.prototype,这样a instanceof A会返回true,完全符合类实例的预期
另一种可选实现思路(继承Function)
如果你不想用闭包,也可以让A直接继承Function,但这种写法相对少见,可读性不如闭包方案:
class A extends Function { constructor() { super('return this.count++'); this.count = 1; // 绑定this到实例,避免调用时this指向丢失 return this.bind(this); } }
这种方式让A的实例本身就是函数,通过super定义函数执行逻辑,在实例上维护count属性,同样能满足需求,但日常开发中闭包方案会更常用、更直观。
内容的提问来源于stack exchange,提问作者leo277
相关产品推荐
相关产品推荐

