繁体   English   中英

在 JavaScript class 方法中,即使使用箭头函数也无法在 addEventListener() 中使用“this”。 如何解决这个问题

[英]In JavaScript class method, Unable to use 'this' inside addEventListener() even using arrow functions. how to solve this issue

我为井字游戏编写了 class。 代码工作正常,但我必须在 class 定义中使用 object 名称来调用一些方法而不是“this”关键字。 当方法作为回调传递给 addEventListener() 时,就会出现问题。 我试图通过使用箭头函数定义方法来解决它。 但是 JS 显示错误“无法读取未定义的属性”错误。 我将如何克服这种情况。

这是 class 实现。 你可以看到我使用了 game.turnClick 而不是 this.turnClick

    class TicTacToe{
    constructor(aiPlayer,humanPlayer){

        this.aiPlayer=aiPlayer;
        this.humanPlayer=humanPlayer;
        this.winCombos=[
            [0,1,2],
            [3,4,5],
            [6,7,8],
            [0,3,6],
            [1,4,7],
            [2,5,8],
            [0,4,8],
            [2,4,6]
        ];
        this.originalBoard=Array.from(Array(9).keys());
        this.gameWon=null;
        this.cells=document.querySelectorAll('.cell');


    }
    startGame(){
        //const cells=document.querySelectorAll('.cell');
        this.cells.forEach(function(cell){
            cell.innerHTML="";
            cell.addEventListener('click',game.turnClick);
        })
    }
    turnClick(e){
        game.turn(e.target.id,game.humanPlayer);
        if(!game.isTie()&&!game.gameWon){
            window.setTimeout(function(){
                game.turn(game.bestSquare(),game.aiPlayer);
                game.isTie();
            },1500);

        }
    }
    turn(squareId,player){
        this.originalBoard[squareId]=player;
        const square=document.getElementById(squareId);
        square.innerHTML=player;
        document.querySelector('#click').play();
        square.removeEventListener('click',game.turnClick);
        this.gameWon=this.checkWin(this.originalBoard,player);
        if(this.gameWon){
            this.gameOver();
        }



    }
    checkWin(board,player){
        let playedSquares=[];
        board.forEach(function(el,i){
            if(el===player){
                playedSquares.push(i);
            }
        })
        console.log(playedSquares);
        for(let [index,win] of this.winCombos.entries()){
            if(win.every((el)=>{return playedSquares.includes(el)})){
            return {index,player};
            break;
            }
        }
        return null;
    }
    gameOver(){
        for(let index of this.winCombos[this.gameWon.index] ){
            const square=document.getElementById(index);
            square.style.backgroundColor= this.gameWon.player===this.humanPlayer?"blue":"red";
        }
        //const cells=document.querySelectorAll('button.cell');
        this.cells.forEach(function(cell){
            cell.removeEventListener('click',game.turnClick);
        });
        this.declareWin(this.gameWon.player===this.humanPlayer?'You Won !!! Hurray...':'You loose,AI beat you...');
    }
    emptySquares(){
        return this.originalBoard.filter((el)=>typeof el==='number');
    }
    bestSquare(){
        //return this.emptySquares()[0];
        return this.minimax(this.originalBoard, this.aiPlayer).index;
    }
    isTie(){
        if(this.emptySquares().length===0&& !this.gameWon){
            this.cells.forEach(function(cell){
                cell.style.backgroundColor='green';
                cell.removeEventListener('click',game.turnClick);
            });
            this.declareWin(' You managed tie the game. congrats !!!');
            return true;
        }
        else{
            return false;
        }
    }
    declareWin(msg){
        if(msg.includes('won')||msg.includes('tie')){
            document.querySelector('#winOrTie').play();
        }
        else{
            document.querySelector('#lost').play();
        }
        document.querySelector('.endgame .message').innerText=msg;
        document.querySelector('.endgame').classList.add('show');
    }
    minimax(newBoard,player){
        let availSpots = this.emptySquares();

        if (this.checkWin(newBoard, this.humanPlayer)) {
            return {score: -10};
        } else if (this.checkWin(newBoard, this.aiPlayer)) {
            return {score: 10};
        } else if (availSpots.length === 0) {
            return {score: 0};
        }
        let moves = [];
        for (let i = 0; i < availSpots.length; i++) {
            let move = {};
            move.index = newBoard[availSpots[i]];
            newBoard[availSpots[i]] = player;

            if (player === this.aiPlayer) {
                let result = this.minimax(newBoard, this.humanPlayer);
                move.score = result.score;
            } else {
                let result = this.minimax(newBoard, this.aiPlayer);
                move.score = result.score;
            }

            newBoard[availSpots[i]] = move.index;

            moves.push(move);
        }

        let bestMove;
        if(player === this.aiPlayer) {
            let bestScore = -10000;
            for(let i = 0; i < moves.length; i++) {
                if (moves[i].score > bestScore) {
                    bestScore = moves[i].score;
                    bestMove = i;
                }
            }
        } else {
            let bestScore = 10000;
            for(let i = 0; i < moves.length; i++) {
                if (moves[i].score < bestScore) {
                    bestScore = moves[i].score;
                    bestMove = i;
                }
            }
        }

        return moves[bestMove];

    }
}

这是包含完整代码https://github.com/harikrishnan-ak/Tic_Tac_Toe的 gitHub 存储库

cell.addEventListener('click',game.turnClick.bind(game));

您可能需要将回调方法的上下文绑定到实例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM