NOTE:この質問は、ECMAScriptバージョン3または5の観点から寄せられたものです。ECMAScript 6のリリースで新機能が導入され、回答が古くなっている可能性があります。
JavaScriptのvar
キーワードの機能と、その違いは何ですか。
var someNumber = 2;
var someFunction = function() { doSomething; }
var someObject = { }
var someObject.someProperty = 5;
そして
someNumber = 2;
someFunction = function() { doSomething; }
someObject = { }
someObject.someProperty = 5;
?
どちらを使用するのですか。また、なぜ、どうしますか。
あなたがグローバルな範囲にいるなら、それほど大きな違いはありません。説明のための Kangax's 回答を読む
もしあなたが関数の中にいるなら、var
はローカル変数を作成します、 "no var"はそれが変数を見つけるかグローバルスコープに達するまでスコープチェーンを検索します:
// These are both globals
var foo = 1;
bar = 2;
function()
{
var foo = 1; // Local
bar = 2; // Global
// Execute an anonymous function
(function()
{
var wibble = 1; // Local
foo = 2; // Inherits from scope above (creating a closure)
moo = 3; // Global
}())
}
代入をしていないのなら、var
を使う必要があります。
var x; // Declare x
違いがあります。
var x = 1
現在のスコープ内でvariablex
を宣言する(別名実行コンテキスト)。宣言が関数内にある場合はローカル変数が宣言され、グローバルスコープにある場合はグローバル変数が宣言されます。
一方、x = 1
は単なるプロパティの割り当てです。まずスコープチェーンに対してx
を解決しようとします。そのスコープチェーンのどこかで見つかった場合、代入を実行します。 x
が見つからない場合は、グローバルオブジェクトのx
プロパティ(スコープチェーンの最上位オブジェクト)を作成します)のみが検索されます。
グローバル変数を宣言するのではなく、グローバルプロパティを作成します。
この2つの違いは微妙で、変数宣言でもpropertiesが作成される(Variableオブジェクトに対してのみ))とJavascriptのすべてのプロパティ(ECMAScript)にはそれぞれのプロパティを説明するフラグがあるReadOnly、DontEnumおよびDontDelete。
変数宣言はDontDeleteフラグを使ってプロパティを作成するので、var x = 1
とx = 1
の違いは(グローバルスコープで実行した場合)、前者の1つ(変数宣言)はDontDelete可能なプロパティを作成し、後者は作成しないということです。結果として、この暗黙の代入によって作成されたプロパティはグローバルオブジェクトから削除でき、前のもの(変数宣言によって作成されたもの)は削除できません。
しかし、これは単なる理論であり、実際には2つのの間にはもっと多くの違いがあります。これは、実装のさまざまなバグ(IEからのものなど)によるものです。
それがすべて理にかなっていることを願っています:)
[更新2010/12/16]
ES5(ECMAScript 5;最近標準化された、第5版の言語)には、いわゆる "厳密モード"(オプトイン言語モード)があります。これは、宣言されていない割り当ての動作をわずかに変更します。厳密モードでは、宣言されていない識別子への代入はReferenceErrorです。この理由は、誤った割り当てをキャッチして、不要なグローバルプロパティが作成されないようにするためです。例えば、 私のcompatテーブル です。
それが " local と global "の違いだと言っても完全に正確ではありません。
それを " local と nearest "の違いと考える方が良いかもしれません。最寄りの地域は確実にグローバルになることができますが、必ずしもそうではありません。
/* global scope */
var local = true;
var global = true;
function outer() {
/* local scope */
var local = true;
var global = false;
/* nearest scope = outer */
local = !global;
function inner() {
/* nearest scope = outer */
local = false;
global = false;
/* nearest scope = undefined */
/* defaults to defining a global */
public = global;
}
}
Javascriptがブラウザで実行されると、コードはすべて次のようにwithステートメントで囲まれます。
with (window) {
//Your code
}
with
- MDN の詳細情報
var
は変数現在のスコープ内を宣言しているので、var
ウィンドウの内側 を宣言してもまったく宣言していなくても違いはありません。
違いは、ウィンドウの中にいないときです。関数の内部またはブロックの内部.
var
を使用すると、同じ名前の外部変数を隠すことができます。このようにして、「プライベート」変数をシミュレートできますが、それは別のトピックです。
経験則では、常にvar
を使用します。そうしないと、微妙なバグが発生する危険があります。
編集:私が受けた批評の後、私は以下を強調したいと思います。
var
は変数現在のスコープ内を宣言しますwindow
ですvar
を使用しないと、グローバルスコープでvar
が暗黙的に宣言されます(ウィンドウ)var
を使用してグローバルスコープ(ウィンドウ)内で変数を宣言することは、それを省略することと同じです。var
を使用してwindowとは異なるスコープで変数を宣言するのは、var
を指定せずに変数を宣言するのと同じことではありません var
を明示的に宣言するのは良い習慣だからです。変数を宣言するにはalwaysキーワードvar
を使用する必要があります。どうして?コーディングの習慣はそれ自体で十分なはずですが、var
キーワードを指定せずに変数を宣言すると、その変数は global スコープで宣言されます(このような変数は「暗黙の」グローバルと呼ばれます)。 Douglas Crockford 暗黙のグローバルを絶対に使用しないことをお勧めします 、および に従ってください - Apple JavaScript Coding Guidelines :
var
キーワードを使用せずに作成された変数はグローバルスコープで作成され、関数が戻るときにガベージコレクションされないため、メモリリークの可能性があります。
つまり、要するに、常にvar
キーワードを使用して変数を宣言するということです。
これは、ローカル変数をvar
で宣言していないことからどうやって捕らえられるかの非常に良い例です:
<script>
one();
function one()
{
for (i = 0;i < 10;i++)
{
two();
alert(i);
}
}
function two()
{
i = 1;
}
</script>
(i
ループ内でローカルに宣言されているのではなくグローバルに宣言されているため、ループの繰り返しごとにfor
がリセットされます)最終的に無限ループになります
ほとんどの場合はvar
を使用する方が良いと思います。
ローカル変数は、グローバルスコープの変数よりも常に高速です。
変数の宣言にvar
を使用しないと、その変数はグローバルスコープになります。
詳しくは、Googleで "scope chain JavaScript"を検索してください。
var
を使用しないでください。var
はES6より前の変数宣言方法でした。私たちは今 将来 であり、あなたはそのようにコーディングしているべきです。
const
とlet
を使うconst
は95%のケースで使われるべきです。変数参照が変更できないようにするため、配列、オブジェクト、およびDOMノードの各プロパティは変更される可能性があり、おそらくconst
になります。
let
は、再割り当てが必要な変数に使用する必要があります。これにはforループが含まれます。初期化を超えてvarName =
を書く場合は、let
を使用してください。
他のほとんどの言語で期待されているように、両方ともブロックレベルのスコープを持っています。
var
- グローバル変数なし。
_ always _ ローカルコンテキストでのinitグローバル変数 - 邪悪なので、_ var
ステートメントを使用することを強く推奨します。しかし、あなたがこの汚いトリックを必要とするなら、あなたはページの最初にコメントを書くべきです:
/* global: varname1, varname2... */
他の違い
var a = a || [] ; // works
しながら
a = a || [] ; // a is undefined error.
var
を使用することは、変数がグローバルスコープを乱雑にして、変数が互いに衝突して、不要な上書きを引き起こすのを防ぐために常に良い考えです。
@Chris Sは、var
とno var
の間の実際的な違い(および危険性)を示すNiceの例を挙げました。もう一つ、これは特に危険だと思う。違いは非同期環境でしか見られず、テスト中に簡単に抜けてしまうからだ。
次のスニペットが["text"]
を出力することを期待していると思いますが:
function var_fun() {
let array = []
array.Push('text')
return array
}
console.log(var_fun())
次のスニペットも同様です(let
の前にarray
がないことに注意してください)。
function var_fun() {
array = []
array.Push('text')
return array
}
console.log(var_fun())
データ操作を非同期に実行しても、単一のexecutorで同じ結果が得られます。
function var_fun() {
array = [];
return new Promise(resolve => resolve()).then(() => {
array.Push('text')
return array
})
}
var_fun().then(result => {console.log(result)})
しかし、複数のものとは異なる動作をします。
function var_fun() {
array = [];
return new Promise(resolve => resolve()).then(() => {
array.Push('text')
return array
})
}
[1,2,3].forEach(i => {
var_fun().then(result => {console.log(result)})
})
しかしletを使う:
function var_fun() {
let array = [];
return new Promise(resolve => resolve()).then(() => {
array.Push('text')
return array
})
}
[1,2,3].forEach(i => {
var_fun().then(result => {console.log(result)})
})
これは、この概念を理解するために私が作成したサンプルコードです。
var foo = 5;
bar = 2;
fooba = 3;
// Execute an anonymous function
(function() {
bar = 100; //overwrites global scope bar
var foo = 4; //a new foo variable is created in this' function's scope
var fooba = 900; //same as above
document.write(foo); //prints 4
document.write(bar); //prints 100
document.write(fooba); //prints 900
})();
document.write('<br/>');
document.write('<br/>');
document.write(foo); //prints 5
document.write(bar); //prints 100
document.write(fooba); //prints 3
あなたがvarを使用せずに変数を使用するならあなたがコードの中で、そして起こることは自動的にvar var_nameがグローバルスコープに置かれることです:例えば
someFunction() {
var a = some_value; /*a has local scope and it cannot be accessed when this
function is not active*/
b = a; /*here it places "var b" at top of script i.e. gives b global scope or
uses already defined global variable b */
}
var の有無にかかわらず、そして関数の内側または外側で変数を宣言するとき、人々は混乱しているようです。以下は、これらの手順を説明するための深い例です。
a = 1;// Defined outside the function without var
var b = 1;// Defined outside the function with var
alert("Starting outside of all functions... \n \n a, b defined but c, d not defined yet: \n a:" + a + "\n b:" + b + "\n \n (If I try to show the value of the undefined c or d, console.log would throw 'Uncaught ReferenceError: c is not defined' error and script would stop running!)");
function testVar1(){
c = 1;// Defined inside the function without var
var d = 1;// Defined inside the function with var
alert("Now inside the 1. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
a = a + 5;
b = b + 5;
c = c + 5;
d = d + 5;
alert("After added values inside the 1. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
};
testVar1();
alert("Run the 1. function again...");
testVar1();
function testVar2(){
var d = 1;// Defined inside the function with var
alert("Now inside the 2. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
a = a + 5;
b = b + 5;
c = c + 5;
d = d + 5;
alert("After added values inside the 2. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
};
testVar2();
alert("Now outside of all functions... \n \n Final Values: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n You will not be able to see d here because then the value is requested, console.log would throw error 'Uncaught ReferenceError: d is not defined' and script would stop. \n ");
alert("**************\n Conclusion \n ************** \n \n 1. No matter declared with or without var (like a, b) if they get their value outside the function, they will preserve their value and also any other values that are added inside various functions through the script are preserved.\n 2. If the variable is declared without var inside a function (like c), it will act like the previous rule, it will preserve its value across all functions from now on. Either it got its first value in function testVar1() it still preserves the value and get additional value in function testVar2() \n 3. If the variable is declared with var inside a function only (like d in testVar1 or testVar2) it will will be undefined whenever the function ends. So it will be temporary variable in a function.");
alert("Now check console.log for the error when value d is requested next:");
alert(d);
結論
- Varの有無にかかわらず(a、bのように)宣言しても、関数の外部で値を取得しても、それらの値は保持され、スクリプトを通じてさまざまな関数の内部で追加された値も保持されます。
- 変数が関数内でvarなしで宣言されている場合(cのように)、それは前の規則のように振る舞い、それ以降はすべての関数でその値を保持します。関数testVar1()で最初の値を取得した場合でも、値を保持したまま関数testVar2()で追加の値を取得します。
- 変数が関数内でのみvarで宣言されている場合(testVar1またはtestVar2のdのように)、関数が終了するたびに未定義になります。そのため、関数内の一時変数になります。
誰かがこれを学ぼうとしているので、これは私がそれを見る方法です。上記の例は、初心者にとっては少し複雑すぎるかもしれません。
このコードを実行すると、
var local = true;
var global = true;
function test(){
var local = false;
var global = false;
console.log(local)
console.log(global)
}
test();
console.log(local);
console.log(global);
出力はfalse、false、true、trueのようになります。
関数内の変数は外部の変数とは別のものと見なされるため、ローカル変数という用語と割り当ての際にvarを使用したためです。もしあなたが関数の中のvarを取り去るならば、それは今このように読む:
var local = true;
var global = true;
function test(){
local = false;
global = false;
console.log(local)
console.log(global)
}
test();
console.log(local);
console.log(global);
出力はfalse、false、false、falseです。
これは、ローカルスコープまたは関数内に新しい変数を作成するのではなく、単にグローバル変数を使用してそれらをfalseに再割り当てするためです。
ブラウザのウィンドウオブジェクトに変数をアタッチするつもりがない限り、varキーワードを使用してください。 これは、スコープ設定と、varキーワードを使用したローカルスコープ設定とローカルスコープ設定の違いを説明するリンクです。
Varキーワードを使用せずに変数が定義されると、単純な「代入」操作になります。
値がjavascriptで変数に代入されると、インタプリタはまず代入と同じコンテキスト/スコープ内で「変数宣言」を見つけようとします。インタプリタがdummyVariable = 20
を実行するとき、それは関数の始めでdummyVariableの宣言を調べます。 (すべての変数宣言はJavaScriptインタプリタによってコンテキストの先頭に移動されるため、これをホイストと呼びます)
javascriptでホイストする もご覧になることをお勧めします。
"var"変数を使用しないと、変数は値を設定するときにのみ定義できます。例では:
my_var;
グローバルスコープ または その他のスコープ で作業することはできません。それは次のような価値があるはずです。
my_var = "value";
その一方で、あなたはvaiableのように定義することができます。
var my_var;
その値はundefined
です(その値はnull
ではなく、興味深いことにnull
と等しくありません)。