Node.js/JavaScript中Object.setPrototypeOf()数组遍历场景下失效问题
问题原因
- 最常见的诱因是
loadFiles()为异步方法:你当前同步执行loadFiles()拿到的是Promise实例而非解析后的普通对象数组,对Promise调用map方法自然不会按预期遍历对象修改原型。你单对象测试时应该是在异步回调/await拿到结果后操作,所以流程正常。 - 次要排查点:确认
loadFiles()解析后的返回值是可枚举的普通自有对象,如果返回值是被冻结/密封的对象,或者原型链被篡改的特殊对象,Object.setPrototypeOf操作会静默失败。 - 额外代码bug:你当前
Player类的构造函数逻辑有问题,第二个入参是_id,但内部错误赋值为this.age = _age,会导致id属性丢失。
修复方案
方案1:实例重建(更推荐,无性能隐患)
不要直接修改对象原型,直接新建Player实例后合并已有的属性值,既可以保证类方法正常挂载,也不会触发JS引擎的原型链优化降级:
class Player { constructor(_name,_id) { this.name = _name; this.id = _id; // 修复原参数赋值错误 this.score = 0; } addScore(x) {this.score += x} multiplyScore(x) {this.score *= x} removeScore(x) {this.score -= x} } // 如果loadFiles是异步方法,必须加await等待结果解析完成 const players = (await loadFiles()).map(x => Object.assign(new Player(), x));
验证时console.log(players[0].constructor.name)会正常输出Player,所有类方法都可正常调用。
方案2:修复原setPrototypeOf写法
如果一定要用修改原型的方式,先确保拿到的是解析后的数组:
// 等待异步方法返回实际的对象数组 const rawPlayers = await loadFiles(); const players = rawPlayers.map(x => Object.setPrototypeOf(x, Player.prototype));
注意:
Object.setPrototypeOf会修改JS引擎对对象的性能优化,非必要不推荐使用。
内容的提问来源于stack exchange,提问作者Wassim Tahraoui
相关产品推荐
相关产品推荐

