JavaScript原型模式下对象初始化时属性Getter/Setter的正确实现
解决异步属性获取与Getter栈溢出问题
首先来说你遇到的栈溢出错误——这是因为你在attribute的getter里写了return this.attribute,当你访问this.attribute时,会再次触发这个getter,形成无限递归调用,最终导致调用栈被撑爆,抛出Maximum call stack size exceeded错误。
接下来我们一步步解决你的核心需求:在保持原型结构的前提下,通过异步函数获取属性值,同时避免重复请求和错误。
核心思路
- 用内部变量缓存结果:不要直接在getter里访问同名属性,改用一个带下划线的内部变量(比如
_attribute)来存储异步请求的结果,避免递归调用。 - 处理异步逻辑:由于
httpRequest是异步操作,我们需要用Promise来管理它的结果,确保能正确获取到异步返回的值。 - 缓存请求避免重复调用:第一次调用getter时发起请求,之后直接返回缓存的Promise,不用重复发起请求。
正确实现代码
var objectName = function(){} // 把functionOne提取到外部,避免每次initialize都重新定义 function functionOne() { // 假设httpRequest是异步操作,这里先把它包装成Promise(如果原本不是的话) return new Promise((resolve, reject) => { // 替换成你的实际http请求逻辑,比如fetch/XMLHttpRequest fetch('/your-api-url') .then(response => response.json()) .then(data => resolve(data)) .catch(error => reject(error)); }); } objectName.prototype.initialize = function() { // 初始化内部缓存变量,用于存储异步请求的Promise/结果 this._attribute = null; Object.defineProperty(this, "attribute", { get: async function() { // 如果还没有发起请求,就调用functionOne获取Promise并缓存 if (!this._attribute) { this._attribute = functionOne(); } // 等待Promise完成,返回实际结果 return await this._attribute; }, // 可选:如果需要支持设置属性值,定义setter set: function(newValue) { // 把新值包装成Promise,保持getter返回值的一致性 this._attribute = Promise.resolve(newValue); } }); }
使用方式
当你创建实例并初始化后,需要用await或者.then()来获取异步属性的值:
const instance = new objectName(); instance.initialize(); // 方式1:用.then()处理 instance.attribute.then(data => { console.log(data); // 这里拿到异步请求的结果 }); // 方式2:用async/await async function getAttribute() { const data = await instance.attribute; console.log(data); } getAttribute();
额外说明
- 如果你的
httpRequest本身已经返回Promise,那可以直接在functionOne里返回它,不用额外包装。 - 内部缓存变量用下划线开头是JavaScript里的约定俗成,表示这是内部私有变量,外部不要直接访问。
- 如果你希望属性初始化时就发起请求(而不是第一次访问时才发起),可以在
initialize里直接赋值this._attribute = functionOne();,这样实例初始化后请求就开始了。
内容的提问来源于stack exchange,提问作者jtomasrl
相关产品推荐
相关产品推荐

