在我将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
中没有定义播放器。
答案 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);