我怎样才能从另一个稍后声明的范围使用 $(this) ?

How can I use $(this) from another scope that is only later declared?

这是我的代码。这是一款基于翻转 2 张卡片并匹配它们的卡片记忆游戏。

首先,如何定义变量 $dis 以便它使用单击事件函数范围内的 $(this)?

var checkMatch = function(){
    if ($clicked.length > 1){
        if ($card1 === $card2){
            $dis.toggleClass('match');
            $matched.push($clicked);
            console.log('MATCH');
            $clicked = [];
            console.log($matched);
            console.log($clicked);
        }else {
            $clicked = [];
            $('.card').removeClass('open show');
            console.log('NOT A MATCH!')
        };
    }else{

    };
};

这是完整的项目:https://jsfiddle.net/z1fzfu69/

我遇到的另一个问题是我的代码发现所有卡片都匹配,它应该得到我点击的 2 张卡片,将它们放入一个数组中并进行比较。但所有这些结果都是 "MATCH"。

您有几种方法可以使 $dis 在点击上下文中等于 $(this)

最简单的方法是简单地拥有一个名为 $dis 的全局变量(或者至少在它们共享的范围内),然后在您的点击事件中,在您调用 checkMatch().

let $dis;
$('.card').click(() => {
  $dis = $(this);
  checkMatch();
});

另一种可能更简洁的方法是简单地 call() 函数并传入 this。您根本不必使用 $dis,您可以直接使用 $(this)

$('.card').click(() => {
  checkMatch.call(this);
});

var checkMatch = function(){
  if ($clicked.length > 1){
    if ($card1 === $card2){
        $(this).toggleClass('match');
        $matched.push($clicked);
        console.log('MATCH');
        $clicked = [];
        console.log($matched);
        console.log($clicked);
    }else {
        $clicked = [];
        $('.card').removeClass('open show');
        console.log('NOT A MATCH!')
    };
  } else {

  };
};

使用call(),第一个参数是this在函数内部的意思。

抱歉,昨天我修复你的代码时睡过头了,

你的问题只是关于$(this)。

但是当我看你的代码时我发现了一些错误,所以我决定修复它们而不是只回答你的问题(只是在睡觉前消磨时间)

samanime好好回答你的问题,我就不再解释了。

这是我的代码。看起来很难看,但我让它尽可能简单。也许你可以在这里学到很多东西。

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Matching Game</title>
    <meta name="description" content="">
    <link rel="stylesheet prefetch" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css">
    <link rel="stylesheet prefetch" href="https://fonts.googleapis.com/css?family=Coda">
    <!--<link rel="stylesheet" href="css/app.css">-->
    <style>
    html {
    box-sizing: border-box;
}

*,
*::before,
*::after {
    box-sizing: inherit;
}

html,
body {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
}

body {
    /*background: #ffffff url('../img/geometry2.png');  Background pattern from Subtle Patterns */
    font-family: 'Coda', cursive;
}

.container {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
}

h1 {
    font-family: 'Open Sans', sans-serif;
    font-weight: 300;
}

/*
 * Styles for the deck of cards
 */

.deck {
    width: 660px;
    min-height: 680px;
    background: linear-gradient(160deg, #02ccba 0%, #aa7ecd 100%);
    padding: 32px;
    border-radius: 10px;
    box-shadow: 12px 15px 20px 0 rgba(46, 61, 73, 0.5);
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    margin: 0 0 3em;
}

.deck .card {
    height: 125px;
    width: 125px;
    background: #2e3d49;
    font-size: 0;
    color: #ffffff;
    border-radius: 8px;
    cursor: pointer;
    display: flex;
    justify-content: center;
    align-items: center;
    box-shadow: 5px 2px 20px 0 rgba(46, 61, 73, 0.5);
}

.deck .card.open {
    transform: rotateY(0);
    background: #02b3e4;
    cursor: default;
}

.deck .card.show {
    font-size: 33px;
}

.deck .card.match {
    cursor: default;
    background: #02ccba;
    font-size: 33px;
}

.deck .card.wrong {
    animation: shake 1s cubic-bezier(0.075, 0.82, 0.165, 1) both;
}

.wrong {
    -webkit-animation-name: wiggle;
    -ms-animation-name: wiggle;
    -ms-animation-duration: 1000ms;
    -webkit-animation-duration: 1000ms;
    -webkit-animation-iteration-count: 1;
    -ms-animation-iteration-count: 1;
    -webkit-animation-timing-function: ease-in-out;
    -ms-animation-timing-function: ease-in-out;
}

@keyframes wiggle {
    0% {transform: rotate(10deg);}
    25% {transform: rotate(-10deg);}
    50% {transform: rotate(20deg);}
    75% {transform: rotate(-5deg);}
    100% {transform: rotate(0deg);}
}

/*
 * Styles for the Score Panel
 */

.score-panel {
    text-align: left;
    width: 345px;
    margin-bottom: 10px;
}

.score-panel .stars {
    margin: 0;
    padding: 0;
    display: inline-block;
    margin: 0 5px 0 0;
}

.score-panel .stars li {
    list-style: none;
    display: inline-block;
}

.score-panel .restart {
    float: right;
    cursor: pointer;
}
.loading{
    color: white;
    position: absolute;
    left: 35%;
    top: 50%;
}
.loading span{
    font-size: 72px;
    font-weight: bold;
}
    </style>
</head>
<body>

    <div class="container">
        <header>
            <h1>Matching Game</h1>
        </header>

        <section class="score-panel">
            <ul class="stars">
                <li><i class="fa fa-star"></i></li>
                <li><i class="fa fa-star"></i></li>
                <li><i class="fa fa-star"></i></li>
            </ul>

            <span class="moves">0</span> Moves

            <div class="restart">
                <i class="fa fa-repeat"></i>
            </div>
        </section>

        <ul class="deck"></ul>

    </div>
    <div class="loading"><i class="fa fa-refresh fa-spin fa-5x fa-fw"></i> <span class="msg">Loading...</span></div>

    <script
    src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
    <!--<script src="js/app.js"></script>-->
    <script>
    $(function(){
        var clicked = [];
        var preventClicked = false;
        var icons = ["fa-diamond", "fa-anchor", "fa-paper-plane-o", "fa-bolt", "fa-cube", "fa-leaf", "fa-bicycle", "fa-bomb"]; //must be 8

        function createGame(icons){
            if(icons.length == 8){
                $('.deck').html('');
                var box = 2* icons.length;
                var num = -1;
                for(a=0; a< icons.length; a++){
                    $('.deck').append('<li class="card" p="'+ a +'"><i class="fa '+ icons[a] +'"></i></li>');
                    $('.deck').append('<li class="card" p="'+ a +'"><i class="fa '+ icons[a] +'"></i></li>'); //twice per icon
                }
                setTimeout(function(){
                    $('.restart').click(); //shuffle now
                    $('.loading').hide();
                }, 500)
            }else{
                alert("error: icon must be 8");
            }
        }

        createGame(icons); //init the game

        // Shuffle function
        $('.restart').click(function () {
            var cards = $('.deck').find('.card');
            cards.removeClass('show open match');
            cards.sort(function () {
                return Math.random() - .5;
            });
            $('.deck').append(cards);
        });


        // Click event that runs functions
        $('.deck').on('click', '.card:not(.match):not(.open)', function(e){ //prevent match and open being clicked again
            if(preventClicked == false){
                preventClicked = true;
                $(this).addClass('open show');
                clicked.push(e.target);
                if(clicked.length > 1){
                    $('.moves').text(parseInt($('.moves').text()) + 1);
                    //checkMatch
                    if($(clicked[0]).attr('p') == $(clicked[1]).attr('p')){
                        $(this).addClass('match');
                        $(clicked[0]).addClass('match');
                        $(clicked[1]).addClass('match');
                        clicked = [];
                        preventClicked = false;
                    }else{
                        setTimeout(function(){
                            $(clicked[0]).removeClass('open show');
                            $(clicked[1]).removeClass('open show');
                            clicked = [];
                            preventClicked = false;
                        }, 800);
                    }
                }else{
                    preventClicked = false;
                }
            }               
        });
    });
    </script>
</body>
</html>