【问题标题】:Node.js/Javascript - Object.setPrototypeOf() not working properlyNode.js/Javascript - Object.setPrototypeOf() 无法正常工作
【发布时间】:2021-10-22 20:47:55
【问题描述】:

我有一个Player 类,它有一些属性,如nameidscore 等...以及修改score 属性的一些方法
在执行过程中我最终将此类的几个实例保存到 JSON 文件中。稍后,我将它们导入回名为players 的数组中。为了在数组中的每个对象中检索类的方法,我执行了以下操作:

class Player {
    constructor(_name,_id) {
        this.name = _name;
        this.age = _age;
        this.score = 0;
    }
    addScore(x) {this.score += x}
    multiplyScore(x) {this.score *= x}
    removeScore(x) {this.score -= x}

}
// The function `loadFiles()` returns: [{name:"foo",id:0,score:15},{name:"bar",id:1,score:9}]
const players = loadFiles().map(x => Object.setPrototypeOf(x, Player.prototype));

通常,当我使用 setPrototypeOf() 方法时,它会返回我选择的类的实例,其中包含来自目标对象的属性值,然后如果我执行 console.log(players[0].constructor.name) 它应该打印出 Player,除了players 中的对象保持完全相同,方法没有添加到它们中,并且它们的 constructor.name 不是 Player
PS:如果我对一个对象执行此操作而不是映射/循环遍历它们的数组,则该过程可以正常工作。

【问题讨论】:

  • 您的代码实际上运行良好,您检查过loadFiles 实际返回的内容吗?
  • @georg 是对的,我在答案中添加了一个 sn-p,表明它根据您在 loadFIles() 问题中发布的值工作

标签: javascript node.js class object oop


【解决方案1】:

代码没有问题,它工作得很好。

class Player {
    constructor(_name,_id) {
        this.name = _name;
        this.age = _age;
        this.score = 0;
    }
    addScore(x) {this.score += x}
    multiplyScore(x) {this.score *= x}
    removeScore(x) {this.score -= x}

}
// The function `loadFiles()` returns: [{name:"foo",id:0,score:15},{name:"bar",id:1,score:9}]
const loadFilesResponse = [{name:"foo",id:0,score:15},{name:"bar",id:1,score:9}];
const players = loadFilesResponse.map(x => Object.setPrototypeOf(x, Player.prototype));
console.log("Score before add: ", players[0].score);
players[0].addScore(3);
console.log("Score after add: ", players[0].score);

loadFiles 可能实际上并没有返回预期的对象,例如它可能返回一个承诺列表(处理承诺时的常见错误)。

【讨论】:

  • 我也是这么想的,但是函数 loadFiles 完美地返回了对象,这里没有使用任何承诺
【解决方案2】:

你有数据,只是从数据中创建对象而不是做对象原型黑客?

const players = loadFiles().map(p => {
  const { name, age, score } = p;
  p = new Player(name, age);
  p.score = score;
  return p;
});

虽然稍微扩展该构造函数会减少它的工作量:

class Player {
  constructor(name, age, score = 0) {
    this.name = name;
    this.age = age;
    this.score = score;
  }
  ...
}

...

const players = loadFiles().map(p => {
  const { name, age, score } = p;
  return = new Player(name, age, score);
});

你可以用两个或三个参数调用构造函数,如果你用两个参数调用它,score 参数将简单地默认为 0。容易得多。

【讨论】:

    猜你喜欢
    • 2016-11-26
    • 1970-01-01
    • 2012-01-20
    • 2015-09-01
    • 2020-07-25
    • 2015-05-23
    • 2012-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多