26

値を割り当てる前にJavaScriptで変数を宣言することに関して、ベストプラクティスのようなものはありますか? スコープの理由で必要になることもありますが、スコープが重要でない場合はどうでしょうか?

// Declare first
(function() {
    var foo = 'bar',
        a = 500,
        b = 300,
        c;

    // Some things get done here with a and b before c can use them...

    c = a * b;    

    // c is now ready to use...
    doSomething(c);
}());

// Declare when needed
(function() {
    var foo = 'bar',
        a = 500,
        b = 300;

    // Some things get done here with a and b before c can use them...

    var c = a * b; 

    // c is now ready to use...
    doSomething(c);
}());

また、オブジェクトリテラルに似たもののベストプラクティスは何だろうと思っています:

// Add property with null assigned to it
var myObj = {
    foo: null,

    doSomething: function() {
        this.foo = 'bar';
    }
};

// Property gets added when value is set
var myObj = {
    doSomething: function() {
        this.foo = 'bar';
    }
};
4

1 に答える 1

24

それは主にスタイルの問題です。

var宣言はスコープの先頭に自動的に引き上げられるため、コードをインタープリターが実行する方法に近いコードを読むことができるように、宣言をスコープの先頭に配置することは理にかなっています。

スコープの先頭で変数を宣言することは、Crockford の推奨事項です。そして、いくつかの一般的な誤解を解消するので、それは理にかなっています.

例えば:

for (var i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i);
    }, 0);
}

var関数スコープがあるため、すべての反復 (およびその中の関数) は同じ を参照しますi。3 つの時間指定関数はすべてループの終了後に実行されるため、上記のスニペットは33 回ログに記録します。

ブロックスコープの経験がある人にとって、上記の動作はあまり明確ではありません。スニペットを書き直す:

var i;
for (i = 0; i < 3; i++) {
    // ...
}

現在、i前のスニペットとまったく同じように、グローバル スコープで宣言されています。しかし、これはそれについてより明確です。


別の誤解:

(function() {
    if (true) {
        var foo = 1;
    } else {
        var foo = 1;
    }
}());

繰り返しますが、ブロック スコープの言語¹ では、上記は完全に有効です。ただし、var宣言は解析時に現在の関数スコープの先頭に引き上げられるため、上記は次と同等です。

(function() {
    var foo;
    var foo;
    if (true) {
        foo = 1;
    } else {
        foo = 1;
    }
}());

変数が 2 回宣言されています。ほとんどのブラウザーは 2 番目の宣言を無視するだけで、コードは "機能" しますが、JSHintなどの静的コード分析ツールは怒鳴りつけます。

1 つの宣言だけで書き直すことができ、完全に有効です。

(function() {
    if (true) {
        var foo = 1;
    } else {
        foo = 1;
    }
}());

しかし、私のようなOCDのようなコーダーは、それがかなり醜いと思うでしょう. 繰り返しますが、スコープの先頭で次のように宣言します。

(function() {
    var foo;
    if (true) {
        foo = 1;
    } else {
        foo = 1;
    }
}());

はるかにきれいに見えます。


繰り返しますが、それは主にスタイルの問題です。個人的には、巨大な関数がある場合、変数が既に宣言されているかどうかを確認してリストに追加するためだけに上にスクロールするのは嫌いです。その場合、var(Crockford の推奨に反して)関数の途中にいくつかの宣言を追加するだけで、個人的には読みやすく維持しやすいと思います。

スタイルの問題なので、できるだけ保守しやすく簡潔なコードにするようにしてください。


コインの反対側では、個人的にはvar、変数が最初に使用されるときに宣言を開始し、ほとんど使用したことを認めます。これは言語の特徴であり、問​​題なく使用できます。

しかし、Crockford の推奨事項に最初から従っていれば、(上記の誤解と同様に) 頭を悩ませることも少なくなり、JavaScript の関数スコープの側面をはるかに早く理解できたであろうことも認めます。


¹ JS 1.7 は を通じてブロック スコープの変数を導入しましletたが、まだ広くサポートされていないことに注意してください。

于 2013-06-04T08:57:11.547 に答える