あなたのコードは実際には問題ありません。global: に不幸な名前を選択しただけですname
。他のもの ( などfoo
) に変更すると、動作します: http://jsfiddle.net/6nuCx/1/
その理由はちょっと不明です。グローバル変数はwindow
オブジェクトのプロパティになります。しかし、オブジェクトには、ウィンドウの名前であるwindow
というプロパティが既にあります。あなたのコードがウィンドウの名前を上書きすることを期待していたので、あなたのコードが機能しなかったことに非常に驚いています。しかし、どうやらそうではありません。(これは、グローバル変数を避けることが最善である理由の良い例です。) とにかく、既存のプロパティと競合しない別の変数名を選択すると、それが整理されます。name
name
しかし、コード内で明らかでない可能性のある何かを行ったので、もう少し深く掘り下げてみましょう (ここでは、foo
混乱を避けるためにバージョンを使用しています)。
// Here, you're defining a global variable called `foo`
var foo ='John';
// Here you have a global function, `displayName`, which accepts an
// *argument* named `foo`
function displayName(foo)
{
// Here, within the function, the symbol `foo` refers to the
// *argument*, not to the global. The global is *hidden* by
// the argument (this is called "shadowing" -- the local
// "shadows" the global).
alert('Hi I am '+foo);
}
そしてあなたのHTMLで:
<!-- Here, `foo` refers to the global variable -->
<button type="button" onclick="displayName(foo)">Display Name</button>
その引数の名前を変更すると、より明確になる可能性があります。
var foo ='John';
function displayName(f)
{
alert('Hi I am '+f);
}
HTML は変更されていません。
<!-- Here, `foo` refers to the global variable -->
<button type="button" onclick="displayName(foo)">Display Name</button>
上記で、グローバル変数を避けるのが最善であり、あなたの問題がその理由の良い例であると述べました。では、どうすればよいのでしょうか。まあ、主に DOM0 ハンドラーを避けることによって (あなたの のようなonclick
)。フィドルを再キャストする方法は次のとおりです。ライブコピー
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<button id="theButton" type="button">Display Name</button>
<script type="text/javascript">
// Start a "scoping function"
(function() {
// Everything within this function is local to the function,
// not global
var name = 'John';
function displayName(n)
{
alert('Hi I am ' + n);
}
// Instead of the onclick= in the markup, hook up here in
// the code
document.getElementById("theButton").onclick = function() {
displayName(name);
};
})();
</script>
</body>
</html>
name
グローバルを作成したり操作したりしていないため、 を自由に使用できたことに注意してください。また、コードはボタンが既に存在することを前提としているため、ボタンの後にコードを配置していることにも注意してください。
addEventListener
さらによいのは、 orを使用attachEvent
してハンドラーを接続することです。
var btn = document.getElementById("theButton");
if (btn.addEventListener) {
btn.addEventListener("click", handler, false);
}
else if (btn.attachEvent) {
btn.attachEvent("onclick", handler);
}
else {
// Punt!
btn.onclick = handler;
}
function handler() {
display(name);
}
ご覧のとおり、古いバージョンの IE (または「互換モード」の新しいバージョン) にはaddEventListener
. これは jQuery のようなライブラリを使用する理由の 1 つですが、ライブラリを使用せずに理解を深めようとしているのは理解できますが、これには正当な理由があります。その上で最高!
そして最後に、あなたは尋ねました:
変数を関数内に配置することで修正できることはわかっていますが、関数の外側で宣言された最初の変数 (スクリプト型の直後の変数) を呼び出す方法はありますか?
上記の答えはどれもありません。:-) 答えは: はい、グローバルを隠していた引数を削除することで、直接参照できます:ライブの例
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var foo ='John';
// Note: No argument declared
function displayName()
{
// Because the argument doesn't shadow it, we can refer
// to foo, because foo is declared in an *enclosing
// context*
alert('Hi I am '+foo);
}
</script>
</head>
<body>
<!-- Note we don't pass any argument ------v -->
<button type="button" onclick="displayName()">Display Name</button>
</body>
</html>