2

我在 JavaScript 中遇到全局变量问题。我尝试做的是在函数外部声明变量,然后在函数内更改它,然后调用另一个函数。从我读过的内容来看,这应该有效,但它只是让我不确定。这是我正在制作的卡片绘图游戏的代码。

var randSuit;
function getRandCard() {
    var randNum;
    var randSuit;
    var randVal;
    randNum = Math.floor(Math.random()*13)+1;
    if (randNum == 1) {
        randVal = "2";
    } else if (randNum == 2) {
        randVal = "3";
    } else if (randNum == 3) {
        randVal = "4";
    } else if (randNum == 4) {
        randVal = "5";
    } else if (randNum == 5) {
        randVal = "6"; 
    } else if (randNum == 6) {
        randVal = "7";
    } else if (randNum == 7) {
        randVal = "8";
    } else if (randNum == 8) {
        randVal = "9"; 
    } else if (randNum == 9) {
        randVal = "10";
    } else if (randNum == 10) {
        randVal = "Jack";
    } else if (randNum == 11) {
        randVal = "Queen";
    } else if (randNum == 12) {
        randVal = "King";
    } else if (randNum == 13) {
        randVal = "Ace";
    }

    randNum = randNum = Math.floor(Math.random()*4)+1;

    if (randNum == 1) {
        randSuit = "Hearts";
    } else if (randNum == 2) {
        randSuit = "Clubs";
    } else if (randNum == 3) {
        randSuit = "Spades";
    } else if (randNum == 4) {
        randSuit = "Diamonds";
    }

    console.log(randSuit);
    var randCard = (randVal + " of " + randSuit);
    //Return the Value of the randomly chosen Card.
    return (randCard);
}

//This function calls the random card from the function above, then applies logic to see if it's the same, then outputs the result.
$(function() {
    $('#drawCard').click(function() {

        var e = document.getElementById("faceValue");
        var faceValue = e.options[e.selectedIndex].text;
        var e = document.getElementById("suit");
        var suit = e.options[e.selectedIndex].text;

        $('#oneCardContainer').slideDown('slow');
        var pickedCard = (faceValue + " of " + suit);

        var randCard = getRandCard();
        console.log (randSuit);

        if (pickedCard == randCard) {
            $("#oneCardResults").val("You Chose a " + pickedCard + " and got a " + randCard + ". \nYou Win!");
        } else if (pickedCard != randCard) {

            $("#oneCardResults").val("You Chose a " + pickedCard + " and got a " + randCard + ". \nYou Lose!");

        }
    });
});

那是我尝试过的代码,我尝试传递的变量是 randSuit。我究竟做错了什么?

4

6 回答 6

4

您正在定义一个名为 的全局变量randSuit,但定义了一个同名的局部变量。当你这样做时randSuit = randSuit;,实际上什么都没有发生,因为左侧和右侧都在引用局部变量。您需要以不同的方式命名它们。

于 2012-04-19T02:06:10.730 回答
3

@Elliot Bonneville 和 @jfriend00 的答案很好,但这里是对局部和全局变量问题背后的理论的一些解释。

JavaScript 使用全局变量和局部变量的方式是,当解释器遇到标识符时,它会在当前范围内搜索它(在您的情况下为:)getRandCard,如果找不到它 - 解释器会转到上面的一个范围,如果它在那里找不到它 - 它会在上面两个范围内等等。

randSuit = randSuit;

在这一行中,这些标识符都将引用同一个局部变量,因为解释器会在本地范围内找到它们,所以这一行实际上什么都不做。

为了引用全局变量,您应该创建对其范围的引用:

var randSuit;
var that = this;    

function getRandCard() {
    ...
}

然后,替换:

randSuit = randSuit;

和:

that.randSuit = randSuit;
于 2012-04-19T02:15:47.383 回答
2

randSuit在函数内部重新声明;该声明隐藏了 global randSuit,因此您的函数正在修改自己的局部变量而不是全局变量。

于 2012-04-19T02:06:52.270 回答
1

当您在函数内部重新声明 randsuit 时,它被私有化为该函数

var randSuit = 5; // not shared
function getRandCard() {
    var randSuit = 3; // not shared
    console.log(randSuit);
}
getRandCard();
console.log(randSuit);

​http://jsfiddle.net/PbBph/

如果你想分享randSuit不要重新声明变量的输出

var randSuit = 5; // shared
function getRandCard() {
    randSuit = 3; // shared
    console.log(randSuit);
}
getRandCard();
console.log(randSuit);

http://jsfiddle.net/PbBph/1/

更好的选择是模块化卡片变量和方法

var cardStack = (function () {
   var randSuit; // protected from global

   return {
      getRandSuit: function () { return randSuit; }, // but still readable
      getRandCard: function () { .... }
   };

}());

var card = cardStack.getRandCard();
    suit = cardStack.getRandSuit();
于 2012-04-19T02:12:54.670 回答
0

试试这个,它是你的代码的缩短版本,应该可以工作:

var randSuit;
function getRandCard() {
    var randNum, randVal;

    var upperCards = ["Jack", "Queen", "King", "Ace"];
    var suits = ["Hearts", "Clubs", "Spades", "Diamonds"];

    randNum = Math.floor(Math.random()*13)+1;
    (randNum < 10) ? randVal++ : randVal = upperCards[randNum-10];

    randSuit = suits[Math.floor(Math.random()*4)];

    // return the value of the randomly chosen card.
    return (randVal + " of " + randSuit);
}

我使用了一些数组和一个三元运算符来大大缩短您的代码。我还消除了不必要的局部randSuit变量,它被限定并覆盖了您的全局对象。

于 2012-04-19T02:12:18.863 回答
0

如果要使用全局变量,请全局定义变量,不要在本地重新定义,只需在本地使用即可。当您在本地重新定义它时,您将创建一个具有相同名称的新局部变量,以取代该范围内的全局变量。


其余部分实际上是评论,但是由于无法在评论中有效地包含代码,因此我将其作为答案的一部分发布。您确实需要将 DRY(不要重复自己)原则应用于您的代码。这是可怕的重复:

randNum = Math.floor(Math.random()*13)+1;
if (randNum == 1) {
    randVal = "2";
} else if (randNum == 2) {
    randVal = "3";
} else if (randNum == 3) {
    randVal = "4";
} else if (randNum == 4) {
    randVal = "5";
} else if (randNum == 5) {
    randVal = "6"; 
} else if (randNum == 6) {
    randVal = "7";
} else if (randNum == 7) {
    randVal = "8";
} else if (randNum == 8) {
    randVal = "9"; 
} else if (randNum == 9) {
    randVal = "10";
} else if (randNum == 10) {
    randVal = "Jack";
} else if (randNum == 11) {
    randVal = "Queen";
} else if (randNum == 12) {
    randVal = "King";
} else if (randNum == 13) {
    randVal = "Ace";
}
randNum = randNum = Math.floor(Math.random()*4)+1;

if (randNum == 1) {
    randSuit = "Hearts";
} else if (randNum == 2) {
    randSuit = "Clubs";
} else if (randNum == 3) {
    randSuit = "Spades";
} else if (randNum == 4) {
    randSuit = "Diamonds";
}

并且可以用这个重复性更少的代码代替:

var cards = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "Jack", "Queen", "King", "Ace"];
randVal = cards[Math.floor(Math.random() * cards.length)];

var suits = ["Hearts", "Clubs", "Spades", "Diamonds"];
randSuit = suits[Math.floor(Math.random() * suits.length)];
于 2012-04-19T02:18:15.937 回答