strictモードとは?[JavaScript]:.NET TIPS
堅牢なJavaScriptコードを書く上でstrictモードはぜひ使いたい機能だが、落とし穴もある。本稿ではstrictモードの使い方と注意点を紹介する。
JavaScriptを書いているとき、うっかり未定義の変数を使ってしまったり、変数名のスペルミスをしてしまって、バグを出してしまったことはないだろうか? そんなことを防いでくれるのがstrictモード(厳格モード)だ。本稿では、その使い方と、二つの注意事項を解説する。
strictモードの宣言と効果
「"use strict";」(または「'use strict';」)という1文を置くことで、strictモードになる。
スクリプトの先頭で宣言すれば、スクリプト全体がstrictモードになる。関数の先頭で宣言すれば、その関数内だけがstrictモードになる。それ以外の場所で宣言しても効果はないので注意しよう。
関数スコープでstrictモードを使う例を、次のコードに示す。
// strictモードを使わない例
(function () {
x = 10; // ローカル変数のつもりで書いた変数(先頭のvarを書き忘れ)
var w = 15; // このwは正しくローカル変数
test(); // x=20, w=15
}());
// 上の関数内のxはグローバルスコープになるので、どこからでも変更できる
function test() {
x = 20;
w = 25; // このwは、グローバルスコープの新しい変数になる
}
// strictモードを使う例
(function () {
"use strict";
// 未定義変数はエラーになる
try {
y = 20;
}
catch (e) {
alert(e);
// Edgeでのエラーメッセージ
// ReferenceError: Variable undefined in strict mode
}
}());
関数の先頭に「"use strict";」と書くことで、その関数内がstrictモードになる。関数の途中に書いても有効にならないので注意しよう。
非strictモードでは、変数宣言をしないまま変数を使うと、グローバルスコープで変数が宣言されたものと見なされる。そのため、この例の変数「x」のように、関数内だけで使っているつもりでもグローバルスコープになってしまう。strictモードでは、先頭にvarキーワードを付けて変数を宣言しないとエラーになるので、そのようなミスはなくなる。
なお、この「(function () {……省略……}());」という関数の書き方は即時関数(IIFE、Immediately-invoked function expression)というものだ。無名関数をその場で実行してくれるのである。
strictモードでは上の例のようにvarキーワードの付け忘れを防いでくれる。その他に、変更できないプロパティへの代入や、関数の引数名の重複(例えば、2つの引数を取る関数で、両方の仮引数名を同じ名前で宣言すること)などがチェックされる。詳細は、MSDNやMDNのドキュメントをご覧いただきたい。
このようなメリットのあるstrictモードは、今どきのJavaScriptでは使うのが当たり前だといえるだろう。ただし、使用に当たって気を付けることが2点あるので、以降で説明する。
スクリプト連結の罠
上の例では関数内でstrictモードを宣言した。いちいち関数ごとに宣言しなくても、スクリプトの先頭で宣言すればよさそうなものだが、それには落とし穴がある。
つまり、複数のスクリプトファイルを連結するときに問題になるのだ。全体がstrictモードになっているスクリプトファイルの後ろに、全体が非strictモードになっているスクリプトファイルを連結すると、連結結果は全体がstrictモードになってしまうため、非strictモードのスクリプトの部分でエラーが出てしまう(逆に全体が非strictモードのスクリプトファイルにstrictモードのスクリプトファイルを連結すると、全てが非strictモードになってしまう場合もある)。そのような事態を避けるため、strictモードは関数ごとに宣言する方がよいだろう。
なお、関数を入れ子にしている場合、外側の関数でstrictモードを宣言すれば内側の関数でも有効だ。
非対応ブラウザで挙動が変わる罠
全てのブラウザでstrictモードがサポートされているわけではない。最近のデスクトップPC用ブラウザなら対応しているが、例えばIE9以下やAndroid 4.0以下など、ちょっと古いブラウザの中には対応していないものもある。
非対応ブラウザでも、strictモードの宣言はただの文字列リテラルなので、エラーになることはない。しかし、挙動が変わる場合があるので、strictモード非対応ブラウザでのテストは欠かせない。
例としてeval関数で挙動が変わる例を次のコードに示す。
// strictモード
(function () {
"use strict";
var z = 30;
// strictモードでは、上のzと下のeval内のzは別物
var result = eval("var z = 45; z;");
// z=30, result=45
}());
// 非strictモード
(function () {
var z = 30;
// 非strictモードでは、上のzと下のeval内のzは同じ物
var result = eval("var z = 45; z;");
// z=45, result=45
}());
strictモードでは、ローカル変数zと、eval関数内で宣言している変数zとは別物になるので、eval関数実行後もローカル変数zは30のままだ。ところが、これをstrictモード非対応のブラウザで実行すると、下側のようにeval関数内での代入がローカル変数zに対して行われてしまうため、eval関数実行後のローカル変数zは45に変わってしまう。
このようなモードによって挙動が変わってしまうコードは、(ブラウザが限定できない場合には)書かないようにするしかない。
【コラム】VBのOption Strict
VBの開発者はOption Strictステートメントを連想するかもしれないが、むしろ「"using strict";」はOption Explicitステートメントに近い。
まとめ
つまらないミスを防止するため、関数の先頭には「"use strict";」を書いてstrictモードにしよう。関数を入れ子にする場合は、一番外側の関数だけに書けばよい。
ただし、strictモード非対応ブラウザでは挙動が変わる場合があるので、非対応ブラウザでのテストも必要だ。
カテゴリ:JavaScript 処理対象:言語構文
関連TIPS:Visual Studioで静的HTMLページのJavaScriptコードをデバッグするには?
関連TIPS:異なるデータ型の値を比較するには?(==と===の違いを理解する)[JavaScript]
関連TIPS:文字列が他の文字列に含まれているかを調べるには?[JavaScript]
Copyright© Digital Advantage Corp. All Rights Reserved.