web-dev-qa-db-ja.com

またそれを使用する(または省略する)必要があるのはいつですか?

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;

どちらを使用するのですか。また、なぜ、どうしますか。

1467
Alex

あなたがグローバルな範囲にいるなら、それほど大きな違いはありません。説明のための 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
1296
Greg

違いがあります

var x = 1現在のスコープ内でvariablexを宣言する(別名実行コンテキスト)。宣言が関数内にある場合はローカル変数が宣言され、グローバルスコープにある場合はグローバル変数が宣言されます。

一方、x = 1は単なるプロパティの割り当てです。まずスコープチェーンに対してxを解決しようとします。そのスコープチェーンのどこかで見つかった場合、代入を実行します。 xが見つからない場合は、グローバルオブジェクトのxプロパティ(スコープチェーンの最上位オブジェクト)を作成します)のみが検索されます。

グローバル変数を宣言するのではなく、グローバルプロパティを作成します。

この2つの違いは微妙で、変数宣言でもpropertiesが作成される(Variableオブジェクトに対してのみ))とJavascriptのすべてのプロパティ(ECMAScript)にはそれぞれのプロパティを説明するフラグがあるReadOnly、DontEnumおよびDontDelete。

変数宣言はDontDeleteフラグを使ってプロパティを作成するので、var x = 1x = 1の違いは(グローバルスコープで実行した場合)、前者の1つ(変数宣言)はDontDelete可能なプロパティを作成し、後者は作成しないということです。結果として、この暗黙の代入によって作成されたプロパティはグローバルオブジェクトから削除でき、前のもの(変数宣言によって作成されたもの)は削除できません。

しかし、これは単なる理論であり、実際には2つのの間にはもっと多くの違いがあります。これは、実装のさまざまなバグ(IEからのものなど)によるものです。

それがすべて理にかなっていることを願っています:)


[更新2010/12/16]

ES5(ECMAScript 5;最近標準化された、第5版の言語)には、いわゆる "厳密モード"(オプトイン言語モード)があります。これは、宣言されていない割り当ての動作をわずかに変更します。厳密モードでは、宣言されていない識別子への代入はReferenceErrorです。この理由は、誤った割り当てをキャッチして、不要なグローバルプロパティが作成されないようにするためです。例えば、 私のcompatテーブル です。

716
kangax

それが " 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;
    }
}
132

Javascriptがブラウザで実行されると、コードはすべて次のようにwithステートメントで囲まれます。

with (window) {
    //Your code
}

with - MDN の詳細情報

varは変数現在のスコープ内を宣言しているので、var ウィンドウの内側 を宣言してもまったく宣言していなくても違いはありません。

違いは、ウィンドウの中にいないときです。関数の内部またはブロックの内部.

varを使用すると、同じ名前の外部変数を隠すことができます。このようにして、「プライベート」変数をシミュレートできますが、それは別のトピックです。

経験則では、常にvarを使用します。そうしないと、微妙なバグが発生する危険があります。

編集:私が受けた批評の後、私は以下を強調したいと思います。

  • varは変数現在のスコープ内を宣言します
  • グローバルな範囲はwindowです
  • varを使用しないと、グローバルスコープでvarが暗黙的に宣言されます(ウィンドウ)
  • varを使用してグローバルスコープ(ウィンドウ)内で変数を宣言することは、それを省略することと同じです。
  • var を使用してwindowとは異なるスコープで変数を宣言するのは、varを指定せずに変数を宣言するのと同じことではありません
  • 常にvarを明示的に宣言するのは良い習慣だからです。
78
kentaromiura

変数を宣言するにはalwaysキーワードvarを使用する必要があります。どうして?コーディングの習慣はそれ自体で十分なはずですが、varキーワードを指定せずに変数を宣言すると、その変数は global スコープで宣言されます(このような変数は「暗黙の」グローバルと呼ばれます)。 Douglas Crockford 暗黙のグローバルを絶対に使用しないことをお勧めします 、および に従ってください - Apple JavaScript Coding Guidelines

varキーワードを使用せずに作成された変数はグローバルスコープで作成され、関数が戻るときにガベージコレクションされないため、メモリリークの可能性があります。

つまり、要するに、常にvarキーワードを使用して変数を宣言するということです。

37
Steve Harrison

これは、ローカル変数をvarで宣言していないことからどうやって捕らえられるかの非常に良い例です:

<script>
one();

function one()
{
    for (i = 0;i < 10;i++)
    {
        two();
        alert(i);
    }
}

function two()
{
    i = 1;
}
</script>

iループ内でローカルに宣言されているのではなくグローバルに宣言されているため、ループの繰り返しごとにforがリセットされます)最終的に無限ループになります

27
Chris S

ほとんどの場合はvarを使用する方が良いと思います。

ローカル変数は、グローバルスコープの変数よりも常に高速です。

変数の宣言にvarを使用しないと、その変数はグローバルスコープになります。

詳しくは、Googleで "scope chain JavaScript"を検索してください。

11
Billy

varを使用しないでください。

varはES6より前の変数宣言方法でした。私たちは今 将来 であり、あなたはそのようにコーディングしているべきです。

constletを使う

constは95%のケースで使われるべきです。変数参照が変更できないようにするため、配列、オブジェクト、およびDOMノードの各プロパティは変更される可能性があり、おそらくconstになります。

letは、再割り当てが必要な変数に使用する必要があります。これにはforループが含まれます。初期化を超えてvarName =を書く場合は、letを使用してください。

他のほとんどの言語で期待されているように、両方ともブロックレベルのスコープを持っています。

9
Gibolt

var - グローバル変数なし。

_ always _ ローカルコンテキストでのinitグローバル変数 - 邪悪なので、_ varステートメントを使用することを強く推奨します。しかし、あなたがこの汚いトリックを必要とするなら、あなたはページの最初にコメントを書くべきです:

/* global: varname1, varname2... */
8
Anatoliy

他の違い

var a = a || [] ; // works 

しながら

a = a || [] ; // a is undefined error.
8
Pranay Warke

varを使用することは、変数がグローバルスコープを乱雑にして、変数が互いに衝突して、不要な上書きを引き起こすのを防ぐために常に良い考えです。

7
kevinji

@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)})
})
2
thisismydesign

これは、この概念を理解するために私が作成したサンプルコードです。

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
2
newday

あなたが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 */
}
1
Akash Arora

var の有無にかかわらず、そして関数の内側または外側で変数を宣言するとき、人々は混乱しているようです。以下は、これらの手順を説明するための深い例です。

下記のスクリプトを参照してください。ここでjsfiddle

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);

結論

  1. Varの有無にかかわらず(a、bのように)宣言しても、関数の外部で値を取得しても、それらの値は保持され、スクリプトを通じてさまざまな関数の内部で追加された値も保持されます。
  2. 変数が関数内でvarなしで宣言されている場合(cのように)、それは前の規則のように振る舞い、それ以降はすべての関数でその値を保持します。関数testVar1()で最初の値を取得した場合でも、値を保持したまま関数testVar2()で追加の値を取得します。
  3. 変数が関数内でのみvarで宣言されている場合(testVar1またはtestVar2のdのように)、関数が終了するたびに未定義になります。そのため、関数内の一時変数になります。
0
Tarik

誰かがこれを学ぼうとしているので、これは私がそれを見る方法です。上記の例は、初心者にとっては少し複雑すぎるかもしれません。

このコードを実行すると、

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に再割り当てするためです。

0
Danrex

ブラウザのウィンドウオブジェクトに変数をアタッチするつもりがない限り、varキーワードを使用してください。 これは、スコープ設定と、varキーワードを使用したローカルスコープ設定とローカルスコープ設定の違いを説明するリンクです。

Varキーワードを使用せずに変数が定義されると、単純な「代入」操作になります。

値がjavascriptで変数に代入されると、インタプリタはまず代入と同じコンテキスト/スコープ内で「変数宣言」を見つけようとします。インタプリタがdummyVariable = 20を実行するとき、それは関数の始めでdummyVariableの宣言を調べます。 (すべての変数宣言はJavaScriptインタプリタによってコンテキストの先頭に移動されるため、これをホイストと呼びます)

javascriptでホイストする もご覧になることをお勧めします。

0
Simran kaur

"var"変数を使用しないと、変数は値を設定するときにのみ定義できます。例では:

my_var;

グローバルスコープ または その他のスコープ で作業することはできません。それは次のような価値があるはずです。

my_var = "value";

その一方で、あなたはvaiableのように定義することができます。

var my_var;

その値はundefinedです(その値はnullではなく、興味深いことにnullと等しくありません)。

0
umut