getElementByIdと変数スコープ
簡単な3つの要素(input button, input text,div)をもち、ボタンが押されるとテキストボックの値をdivタグ内にコピーするHTMLとjavascriptがあるとします。
scope.html
<html>
<body>
<input type="text" id="txt" />
<input type="button" id="btn" value="Start" />
<div id="lbl"></div>
<script src="scope.js"></script>
</body>
</html>
scope.js(変数スコープエラーのあるプログラム)
const myfunc=()=>{
//スコープ外からローカル変数参照するとエラー
albl.innerHTML=atxt.value;
}
document.addEventListener("DOMContentLoaded", () => {
const abtn = document.getElementById("btn");
const atxt=document.getElementById("txt");
const albl=document.getElementById("lbl");
abtn.addEventListener("click",() => {
myfunc();
});
});
上記のmyfunc関数はイベントハンドラ関数内のオブジェクト変数のスコープ外にあるので上記javascriptは正常に動作しません。教科書通りです。ところが以下のようにmyfunc関数内で参照する変数名の冒頭のaをとると
scope.js(動いてしまうプログラム)
const myfunc=()=>{
lbl.innerHTML=txt.value;
}
document.addEventListener("DOMContentLoaded", () => {
const abtn = document.getElementById("btn");
const atxt=document.getElementById("txt");
const albl=document.getElementById("lbl");
abtn.addEventListener("click",() => {
myfunc();
});
});
上記プログラムは動作します。DOMの要素のid名はそのままグローバルのオブジェクト変数として暗黙的に宣言されています。このため、下記プログラムのようにイベントハンドラ内からもの冒頭のaをとると、スコープ外のmyfuncからイベントハンドラ内のローカル変数が参照できたように見えます。教科書に書いてあることが嘘に見えるコードです。
scope.js(動く上に変数スコープを破壊したように見えるプログラム)
const myfunc=()=>{
//スコープ外からlblやtxtを参照できたように見える
lbl.innerHTML=txt.value;
}
document.addEventListener("DOMContentLoaded", () => {
const btn = document.getElementById("btn");
const txt=document.getElementById("txt");
const lbl=document.getElementById("lbl");
btn.addEventListener("click",() => {
myfunc();
});
});
それならgetElementByIdを使わず、全部グローバル変数を参照した方が潔いのでしょうか。
scope.js(getElementByIdを使わない動作するプログラム)
const myfunc=()=>{
lbl.innerHTML=txt.value;
}
document.addEventListener("DOMContentLoaded", () => {
btn.addEventListener("click",() => {
myfunc();
});
});
いずれにせよ下記のようなid名と変数名を一致させたgetElementByIdは無駄でスコープを破壊したように見えるコードができるので、やめた方が良いのでは、というお話です。
x=getElementById("x");
scope.js(暗黙のグローバル変数を使わないコード)
document.addEventListener("DOMContentLoaded", () => {
const abtn = document.getElementById("btn");
const atxt=document.getElementById("txt");
const albl=document.getElementById("lbl");
const myfunc=()=>{
albl.innerHTML=atxt.value;
}
abtn.addEventListener("click",() => {
myfunc();
});
});