关闭实例未定义

时间:2018-07-13 16:49:30

标签: javascript node.js ecmascript-6

在我将ES6模块转换为使用闭包后,试图弄清楚如何添加新播放器。

所以我基本上是通过工厂创建了一个闭包:

Player.js -现在是一个关闭工厂/工厂

function Player(){
  let players = [], player = this;

  const PlayerType = Object.freeze({
    COMPUTER: "Computer",
    HUMAN: "Human"
  });

  function getPlayerById(playerId){
    const players = getPlayers().filter((player) => {
      return (player.id === +playerId);
    });

    return players;
  }

function addPlayer(name, playerType, symbol) {
    const newPlayer = Object.assign(player, { //player is undefined here
      id: null,
      name,
      symbol,
      type: playerType,
      move: null
    });

    setPlayerMoveLogic(newPlayer);
    players.push(newPlayer);
    setPlayerId(newPlayer);

    return newPlayer;
  }

  return {
    PlayerType,
    players,
    getPlayerById
  };
}

export default Player

所以我叫它:

player = Player();
player.addPlayer("Computer", player.PlayerType.COMPUTER, "O");

现在,如果我看player1,我发现它包含了我返回(公开)的所有子函数。但是,当我添加播放器时,这些播放器什么都没有,因为我最初试图做Object.assign({} ...

Well {}是一个完全独立的对象,其中没有任何内容。因此,因此添加的那些播放器与我尝试向其添加播放器的Player()实例的当前范围无关。

请注意,在我的函数顶部,我有player = this;

好了,我player = Player();做完之后,我希望能够使用该实例。因此,将播放器添加到其播放器数组中。这就是我在这里要做的。

但是它说我的Object.assign中没有定义播放器。

1 个答案:

答案 0 :(得分:4)

我了解您不希望使用es6类或老式原型来执行此操作,而是改用闭包。那不是我的选择,但是,我会说“为什么不呢?”。直到您添加:

  

但是,当我添加播放器时,那些播放器却没有这些,因为我最初是想做Object.assign({} ...

     

(...)

     

请注意,在我的函数顶部,我有player = this;

     

好吧,我做玩家= Player();我希望能够与之合作   实例..因此将玩家添加到其玩家数组。那就是   我想在这里做。

您似乎在这里混淆概念。您的关闭解决方案与this引用的任何种类的实例的使用都不兼容。由于您在调用Player函数时没有使用new关键字。

没有实例。只有您的功能范围。在此范围内,已经有您的players数组。只需将新播放器推到那里,就可以完成。

现在,您似乎希望players数组中包含的对象和Player()函数返回的文字对象公开相同的函数,并通过闭包访问相同的数据。

这可以通过定义一个返回文字对象的函数来完成:

function PlayerInterface() {
    return {
      PlayerType,
      players,
      getPlayerById,
      addPlayer
    };
}

您的Player()函数将返回这样的对象。您的newPlayer对象将在这样的对象上创建:

const newPlayer = Object.assign(PlayerInterface(), {
    id: null,
    name,
    symbol,
    type: playerType,
    move: null
});
players.push(newPlayer);

那样,由于您的关闭,所有这些对象都公开了相同的功能,并且它们在作用域中都具有相同的players数组。

完整摘要:

function Player() {
  let players = [];

  const PlayerType = Object.freeze({
    COMPUTER: "Computer",
    HUMAN: "Human"
  });

  function getPlayerById(playerId) {
    const players = getPlayers().filter((player) => {
      return (player.id === +playerId);
    });

    return players;
  }

  function addPlayer(name, playerType, symbol) {
    const newPlayer = Object.assign(PlayerInterface(), {
      id: null,
      name,
      symbol,
      type: playerType,
      move: null
    });

    //setPlayerMoveLogic(newPlayer);
    players.push(newPlayer);
    //setPlayerId(newPlayer);

    return newPlayer;
  }

  function PlayerInterface() {
    return {
      PlayerType,
      players,
      getPlayerById,
      addPlayer
    };
  }

  return PlayerInterface();
}

const playerObject = Player();

// adding a player through that playerObject object
const computerPlayer = playerObject.addPlayer("Computer", playerObject.PlayerType.COMPUTER, "O");


// adding a player through the newly created player, computerPlayer
computerPlayer.addPlayer("Human", computerPlayer.PlayerType.COMPUTER, "H");

// you can see that both objects share the same private data through the closure 
console.log(computerPlayer.players.length);
console.log(playerObject.players.length);

对于它的价值,这是我将如何使用老式原型(将其命名为Game以避免与实际玩家混淆)来实现的。

function Game() {
  this.players = [];
}

Game.prototype.PlayerType = Object.freeze({
  COMPUTER: "Computer",
  HUMAN: "Human"
});

Game.prototype.getPlayerById = function(playerId){
    const players = this.getPlayers().filter((player) => {
      return (player.id === +playerId);
    });

    return players;
}
  
Game.prototype.addPlayer = function(name, playerType, symbol) {
     const newPlayer = Object.assign({}, {
      id: null,
      name,
      symbol,
      type: playerType,
      move: null
    });

    //setPlayerMoveLogic(newPlayer);
    this.players.push(newPlayer);
    //setPlayerId(newPlayer);

    return newPlayer;
  };

var game1 = new Game();
var game2 = new Game();

var comp11 = game1.addPlayer("Comp1", Game.prototype.PlayerType.COMPUTER, "O");
var hum11 = game1.addPlayer("Joe", Game.prototype.PlayerType.HUMAN, "J");

var comp21 = game2.addPlayer("Comp2", Game.prototype.PlayerType.COMPUTER, "O");
var hum21 = game2.addPlayer("Peter", Game.prototype.PlayerType.HUMAN, "P");
var hum22 = game2.addPlayer("Bob", Game.prototype.PlayerType.HUMAN, "B");

console.log(game1.players);
console.log(game2.players);