2012-04-19 42 views
1

我在JavaScript中遇到全局變量問題。我試過的是在函數外聲明變量,然後在函數內改變它,然後調用另一個函數。從我讀過的內容來看,這應該是有效的,但它只是給了我不確定的東西。這是我製作的卡片繪製遊戲的代碼。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。我究竟做錯了什麼?

回答

3

您正在定義一個名爲randSuit的全局變量,但是也是的一個具有相同名稱的局部變量。當你做randSuit = randSuit;時,實際上沒有任何反應,因爲左側和右側都引用了局部變量。你需要以不同的方式命名它們。

2

你在函數裏面重新聲明randSuit;該聲明隱藏全局randSuit,所以你的函數正在修改它自己的局部變量而不是全局變量。

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變量,它的作用域和覆蓋了你的全局對象。

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(); 
2

@Elliot巴納維亞的和@ jfriend00的回答都不錯,但這裏是有點落後的局部和全局變量問題的理論解釋。

JavaScript與全局和局部變量一起工作的方式是當解釋器遇到一個標識符時,它在當前範圍內搜索它(在你的情況下:getRandCard),如果它找不到它 - 解釋器上面有一個範圍,如果它不能在那裏找到它 - 它會在兩個範圍之上等等。

randSuit = randSuit; 

在這一行這些標識符都將指向同一個局部變量,作爲解釋發現他們無論是在局部範圍內,所以有效這一行什麼也不做。

爲了引用全局變量,你應該建立其範圍參考:

var randSuit; 
var that = this;  

function getRandCard() { 
    ... 
} 

然後,替換:

randSuit = randSuit; 

有:

that.randSuit = randSuit; 
+0

不再是相關的,但你不能真正通過'that'在'randSuit'得到除非'那是'窗口'。 – jli 2014-05-11 00:17:49

+0

@jli true,除非你聲明你的變量是這樣的:'this.randSuit = val;' – 2014-05-11 06:45:12

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)]; 
+0

如果你想要非常聰明,你甚至可以這樣做:'[「1」,「2」,「3」,「 4,5,6,7,8,9,Jack,Queen,King,Ace等[Math.floor(Math.random()* 13)];'因爲你只使用'cards'變量一次。 =) – 2012-04-19 02:20:18