JavaScript工厂函数公共属性存储位置及访问方法咨询
问题根因
你代码里的counter属性实际存储在全局对象上(浏览器环境为window,Node.js环境为globalThis),并没有挂载到foo函数对象上。
- 普通函数直接调用时(没有用
new、没有用call/apply/bind绑定this指向),非严格模式下this默认指向全局对象,你代码中所有this.counter的读写操作,实际都是在操作全局对象的counter属性。 - 这也是为什么连续调用
foo()时计数会递增,但直接访问foo.counter会返回undefined——foo函数对象本身从始至终都没有被添加过counter属性。
补充:如果代码运行在严格模式下,普通函数调用的
this为undefined,你当前的代码会直接抛出Cannot set properties of undefined的错误。
正确实现方案
要实现统计已创建对象总数的需求,有两种常见实现方式:
方案1:直接将计数器挂载到函数对象上
函数在JS中是一等公民,本身就是对象,可以直接挂载属性,访问时直接读函数对象的对应属性即可:
function foo(){ // 直接操作foo函数对象上的counter属性 foo.counter = foo.counter ? foo.counter + 1 : 1; // 工厂函数逻辑:返回自定义的实例对象 const instance = {}; console.log(foo.counter); return instance; } let a = foo(); // 输出1 let b = foo(); // 输出2 console.log(foo.counter); // 正确返回2
方案2:闭包实现私有计数器
如果不希望外部直接修改计数器的值,可以用闭包生成私有变量,仅暴露必要的读取接口:
const foo = (function() { // 私有计数器,外部作用域无法直接访问 let createdCount = 0; return function() { createdCount++; console.log(createdCount); // 可选:给实例暴露读取计数的方法 return { getTotalCreated: () => createdCount }; } })(); let a = foo(); // 输出1 let b = foo(); // 输出2 console.log(a.getTotalCreated()); // 返回2 // 直接访问外部的createdCount会报变量未定义的错误,无法随意篡改计数
内容的提问来源于stack exchange,提问作者Khaled
相关产品推荐
相关产品推荐

