我正在尝试制作一个简单的tic tac toe游戏来学习和练习JavaScript OOP,但遇到了一些困难。
我想在触发game.handleClick
函数时引用game.turn
值。我知道使用this
关键字引用被调用的对象的作用域,而在handleClick
中,this
引用被单击的game-tile-x
。如何引用'handleClick‘函数作用域之外的对象值?
任何帮助都将不胜感激!
<div id="game-board">
<div id="game-tile-1" class="game-tile"></div>
<!-- divs 2-8 -->
<div id="game-tile-9" class="game-tile"></div>
</div>
function Game() {
this.tiles = document.getElementsByClassName('game-tile'),
this.turn = 0;
this.init = function() {
for (let i = 0; i < this.tiles.length; i++) {
// reset game tiles
this.tiles[i].innerHTML = '';
// setup event listeners
this.tiles[i].addEventListener('click', this.handleClick);
}
};
this.handleClick = function() {
let id = parseInt(this.id.replace('game-tile-', ''));
console.log(id); // returns 0, 1, 2, etc.
console.log(this.turn); // returns undefined
};
}
let game = new Game();
game.init();
发布于 2019-05-23 05:17:22
这里有一个基本的解决方案
function Game() {
this.tiles = document.getElementsByClassName('game-tile'),
this.turn = 0;
this.init = function() {
let tile;
for (let i = 0; i < this.tiles.length; i++) {
tile = this.tiles[i];
// reset game tiles
tile.innerHTML = '';
// setup event listeners
// don't mix this for the node & this for the game
// let's bind the context to the game, and the first param to the tile
tile.addEventListener('click', handleClick.bind(this, tile));
}
};
function handleClick(tile) {
let id = parseInt(tile.id.replace('game-tile-', ''));
console.log(id); // returns 0, 1, 2, etc.
console.log(this.turn); // returns undefined
};
}
let game = new Game();
game.init();
发布于 2019-05-23 05:11:45
您可以使用curried函数,并使用游戏实例(this
)调用外部函数,然后可以在内部使用它:
this.tiles[i].addEventListener('click', this.handleClick(this));
//...
this.handleClick = function(game) {
return function() {
let id = parseInt(this.id.replace('game-tile-', ''));
console.log(id); // returns 0, 1, 2, etc.
console.log(game.turn);
};
};
发布于 2019-05-23 05:11:54
有两种方法可以做到这一点,要么将this
保存到稍后要用到的变量中(我们称之为闭包):
例如:
const self = this;
this.handleClick = function() {
const id = parseInt(this.id.replace('game-tile-', ''));
};
或者调用bind,将函数的this
对象绑定到当前作用域的this
:
this.handleClick = function() {
const id = parseInt(this.id.replace('game-tile-', ''));
};
this.handleClick = this.handleClick.bind(this);
PS:
如果可以使用ES6箭头函数:
this.handleClick = () => {
// this will point to the scope where the function is declared
}
如果可以使用ES6类:
class Game(){
constructor(){
this.tiles = document.getElementsByClassName('game-tile'),
this.turn = 0;
for (let i = 0; i < this.tiles.length; i++) {
// reset game tiles
this.tiles[i].innerHTML = '';
// setup event listeners
this.tiles[i].addEventListener('click', this.handleClick);
}
handleClick = () => {
let id = parseInt(this.id.replace('game-tile-', ''));
console.log(id); // returns 0, 1, 2, etc.
console.log(this.turn); // returns undefined
}
}
最好使用ES6语法,因为它对阅读器和机器都更容易理解。如果你担心浏览器的兼容性,可以使用像BabelJS这样的转译器
https://stackoverflow.com/questions/56264956
复制相似问题