関数 JavaScriptの変数の範囲は何ですか?




javascript 変数 保持 (21)

javascriptの変数の範囲は何ですか? 彼らは関数の外ではなく内部で同じスコープを持っていますか? それとも問題なの? また、グローバルに定義されている変数はどこに格納されていますか?


ALMOSTには2種類のJavaScriptスコープしかありません:

  • 各var宣言のスコープは、最もすぐに囲む関数に関連付けられています
  • var宣言の囲み関数がない場合は、グローバルスコープです

したがって、関数以外のブロックは新しいスコープを作成しません。 これは、for-loopsがスコープ外の変数を上書きする理由を説明しています。

var i = 10, v = 10;
for (var i = 0; i < 5; i++) { var v = 5; }
console.log(i, v);
// output 5 5

代わりに関数を使う:

var i = 10, v = 10;
$.each([0, 1, 2, 3, 4], function(i) { var v = 5; });
console.log(i,v);
// output 10 10

最初の例では、ブロック範囲がなかったので、最初に宣言された変数は上書きされました。 2番目の例では、関数のために新しい範囲があったため、最初に宣言された変数はSHADOWEDであり、上書きされませんでした。

JavaScriptスコープに関しては、ほとんどのことを知っておく必要があります。

JavaScriptスコープは実際には直感的ではありませんが、実際には非常にシンプルです。 知っておくべきいくつかの事柄:

  • var宣言はスコープの上部に持ち上げられます。 これは、var宣言がどこで発生しても、var自体が先頭にあるかのようにコンパイラに意味します
  • 同じスコープ内の複数のvar宣言が結合されています

したがって、このコード:

var i = 1;
function abc() {
  i = 2;
  var i = 3;
}
console.log(i);     // outputs 1

次のものと同等です。

var i = 1;
function abc() {
  var i;     // var declaration moved to the top of the scope
  i = 2;
  i = 3;     // the assignment stays where it is
}
console.log(i);

これは直感的ではないように思えるかもしれませんが、不可欠な言語設計者の観点からは理にかなっています。


ES5 それ以前:

Javascriptの変数は、最初はES6レキシカルスコープで機能していました。レキシカルスコープという用語は、コードを「見て」変数の範囲を見ることができることを意味します。

varキーワードで宣言されたすべての変数は関数にスコープされます。ただし、その関数内で他の関数が宣言されている場合、それらの関数は外部関数の変数にアクセスできます。これはスコープチェーンと呼ばれます。それは次のように動作します:

  1. 関数が変数値を解決しようとすると、最初に独自のスコープが検索されます。これは関数本体、つまり中括弧{}の間のすべてです(このスコープ内にある他の 関数変数を除く)。
  2. 関数本体の中で変数を見つけることができない場合は、チェーンまで登り、関数が定義されている関数の変数スコープを調べます。これはレキシカルスコープの意味であり、この関数が定義されたコードを見ることができ、コードを見るだけでスコープチェーンを決定することができます。

例:

// global scope
var foo = 'global';
var bar = 'global';
var foobar = 'global';

function outerFunc () {
 // outerFunc scope
 var foo = 'outerFunc';
 var foobar = 'outerFunc';
 innerFunc();
 
 function innerFunc(){
 // innerFunc scope
  var foo = 'innerFunc';
  console.log(foo);
  console.log(bar);
  console.log(foobar);
  }
}

outerFunc();

私たちは、変数をログに記録しようとしているときに発生foobarと、foobarコンソールに以下の通りです:

  1. 私たちはコンソールにfooを記録しようとしますが、fooは関数innerFunc自体の内部にあります。したがって、fooの値は文字列に解決されますinnerFunc
  2. 我々は、コンソールにバーをログにしようとすると、バーは、機能innerFunc自体の内部に見つけることができません。したがって、スコープチェーン登る必要があります。最初に、関数innerFuncが定義された外部関数を調べます。これが関数outerFuncです。範囲ではouterFunc、我々文字列「outerFunc」を保持する変数バーを、見つけることができます。
  3. foob​​arがinnerFuncに見つかりません。 。したがって、スコープチェーンをinnerFuncスコープまで登る必要があります。また、ここでは見つけることができません、私たちはグローバルスコープ(つまり、最も外側のスコープ)に別のレベルを登る。文字列 'global'を保持する変数foobarがここにあります。スコープチェーンを登った後に変数が見つからない場合、JSエンジンはreferenceErrorをスローします

ES6 (ES 2015)年齢以上:

レキシカルスコープとスコープチェインの同じ概念がまだ適用されていES6ます。しかし、変数を宣言する新しい方法が導入されました。次のものがあります:

  • let :ブロックスコープ変数を作成する
  • const :初期化されなければならないブロックスコープの変数を作成し、再割り当てすることはできません

最大の違いvar及びlet/ constつまりはvar、一方の機能がスコープであるlet/ constブロックがスコープれます。これを説明する例を次に示します。

let letVar = 'global';
var varVar = 'global';

function foo () {
  
  if (true) {
    // this variable declared with let is scoped to the if block, block scoped
    let letVar = 5;
    // this variable declared with let is scoped to the function block, function scoped
    var varVar = 10;
  }
  
  console.log(letVar);
  console.log(varVar);
}


foo();

上記の例では、withと宣言された変数letがブロックスコープであるため、letVarは値globalを記録します。それらはそれぞれのブロックの外に存在しなくなり、変数はifブロックの外側にアクセスできなくなります。


Javascriptでは、スコープチェーンを使用して、指定された関数のスコープを設定します。 通常はグローバルスコープが1つあり、定義された各関数には独自のネストスコープがあります。 別の関数内で定義された関数は、外部関数にリンクされたローカルスコープを持ちます。 スコープを定義するのは常にソース内の位置です。

スコープチェーン内の要素は、基本的に親スコープへのポインタを持つMapです。

変数を解決するとき、javascriptは最も内側のスコープから開始し、外側を検索します。


Brendan Eichによって設計されたJavaScriptのスコープの考え方は、 HyperCardスクリプト言語HyperTalkから来ました。

この言語では、ディスプレイはインデックスカードのスタックと同様に行われました。 バックグラウンドと呼ばれるマスターカードがありました。 それは透明で、下のカードと見ることができます。 このベースカードのコンテンツは、その上に置かれたカードと共有されていました。 一番上に置かれた各カードは、前のカードより優先された独自のコンテンツを持っていましたが、必要に応じて以前のカードにアクセスできました。

これは、JavaScriptスコープシステムの設計方法とまったく同じです。 それはちょうど異なる名前を持っています。 JavaScriptのカードは、 実行コンテキストECMAとして知られています。 これらのコンテキストのそれぞれには、3つの主要な部分が含まれています。 可変環境、レキシカル環境、およびこのバインディング。 カードのリファレンスに戻ると、レキシカル環境には、スタック内の以前のカードからのすべてのコンテンツが含まれています。 現在のコンテキストはスタックの一番上にあり、そこで宣言されたコンテンツは変数環境に格納されます。 名前の衝突の場合、可変環境が優先されます。

このバインディングは、オブジェクトを含むオブジェクトを指します。 時には、スコープや実行コンテキストが、包含オブジェクトがwindowまたはコンストラクタ関数である可能性がある宣言された関数のように、オブジェクトを変更することなく変更されることがありwindow

これらの実行コンテキストは、制御が転送されるたびに作成されます。 コードは実行が開始されると制御が移り、これは主に関数の実行から行われます。

それが技術的な説明です。 実際には、JavaScriptでそれを覚えておくことが重要です

  • スコープは技術的には "実行コンテキスト"
  • コンテキストは、変数が格納される環境のスタックを形成します。
  • スタックの先頭が優先されます(下がグローバルコンテキストです)
  • 各関数は、実行コンテキストを作成します(しかし、必ずしもこのバインディングを新しいものとは限りません)

このページの前の例(5.「Closure」)のいずれかにこれを適用すると、実行コンテキストのスタックに従うことができます。 この例では、スタックに3つのコンテキストがあります。 それらは、外部コンテキスト、直ちに呼び出される関数のコンテキストがvar 6で呼び出され、コンテキストがvar 6のすぐに呼び出される関数の内部で返される関数のコンテキストによって定義されます。

i )外側の文脈。 それは、a = 1の可変環境を有する
ii )IIFE文脈では、a = 1の語彙的な環境を持つが、a = 6の変数環境がスタック内で優先される
iii )返された関数コンテキスト。a = 6の字句環境を持ち、呼び出されたときに警告で参照される値です。


オールドスクールのJavaScript

従来、JavaScriptには2つのタイプのスコープしかありませんでした。

  1. グローバルスコープ :変数は、アプリケーションの始めからアプリケーション全体(*)まで知られています。
  2. 機能スコープ :変数は、関数の先頭から、関数の先頭から宣言されている関数内で認識されます(*)。

違いを説明する答えはすでにたくさんあるので、私はこれについて詳述しません。

現代のJavaScript

最新のJavaScript仕様では、第3のスコープも使用できるようになりました。

  1. ブロックスコープ :宣言されたブロック変数は、宣言された瞬間から認識されます(**)

ブロックスコープ変数を作成するにはどうすればよいですか?

伝統的には、次のような変数を作成します。

var myVariable = "Some text";

ブロックスコープ変数は次のように作成されます:

let myVariable = "Some text";

関数スコープとブロックスコープの違いは何ですか?

関数スコープとブロックスコープの違いを理解するには、次のコードを検討してください。

// i IS NOT known here
// j IS NOT known here
// k IS known here, but undefined
// l IS NOT known here

function loop(arr) {
    // i IS known here, but undefined
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( var i = 0; i < arr.length; i++ ) {
        // i IS known here, and has a value
        // j IS NOT known here
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    };

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( let j = 0; j < arr.length; j++ ) {
        // i IS known here, and has a value
        // j IS known here, and has a value
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    };

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here
}

loop([1,2,3,4]);

for( var k = 0; k < arr.length; k++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS NOT known here
};

for( let l = 0; l < arr.length; l++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS known here, and has a value
};

loop([1,2,3,4]);

// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here

ここで、変数jは最初のforループでのみ認識され、前後では認識されないことがわかります。 しかし、私たちの変数iは関数全体で知られています。

また、ブロックスコープ変数は、ホイストされていないため宣言される前には認識されていないと考えてください。 同じブロックスコープの変数を同じブロック内で再宣言することも許可されていません。 これにより、ブロックスコープ変数は、グローバルにまたは機能的にスコープ化された変数よりもエラーを起こしにくくなります。変数は、ホイストされ、複数の宣言の場合にエラーを生成しません。

今日ブロックスコープ変数を使用するのは安全ですか?

今日の使用が安全かどうかは、使用環境によって異なります。

  • サーバー側のJavaScriptコード( Node.js )を記述している場合は、 letステートメントを安全に使用できます。

  • クライアント側のJavaScriptコードを記述していて、Transizer( Traceur )を使用している場合は、 letステートメントを安全に使用することができますが、コードはパフォーマンスに関して最適なものになる可能性があります。

  • クライアントサイドのJavaScriptコードを記述していて、トランスパイライザを使用していない場合は、ブラウザのサポートを考慮する必要があります。

    現在、2016年2月23日には、 letサポートしていないブラウザや、部分的なサポートしかないブラウザがあります。

    • Internet Explorer 10以降 (サポートなし)
    • Firefox 43以降 (サポートなし)
    • Safari 9以降 (サポートなし)
    • Opera Mini 8以降 (サポートなし)
    • Androidブラウザ4以下(サポートなし)
    • Opera 36以降 (部分的サポート)
    • 丁目51号 (一部支持)

ブラウザのサポートを追跡する方法

この回答を読んでいるときにletステートメントをサポートしているブラウザの最新の概要については、 このCan I Use 」ページを参照してください

(*)グローバル変数と関数スコープ変数は、JavaScript変数がhoistedれて宣言される前に初期化され、使用されます。 これは、宣言が常にスコープの上端にあることを意味します。

(**)ブロックスコープ変数は持ち上げられません



1)グローバルスコープ、機能スコープ、およびwithとcatchスコープがあります。 変数には一般的に 'ブロック'レベルのスコープはありません。withステートメントとcatchステートメントはブロックに名前を追加します。

2)スコープはグローバルスコープまで関数によってネストされています。

3)プロトタイプチェーンを通ってプロパティが解決されます。 with文は、オブジェクトのプロパティ名をwithブロックで定義されたレキシカルスコープに持ち込みます。

EDIT:ECMAAScript 6(Harmony)はletをサポートするように指定されていますが、クロームが 'harmony'フラグを許可することを知っているので、おそらくサポートしています。

ブロックレベルのスコープをサポートするようにしましょうが、キーワードを使用してそれを実現する必要があります。

編集:Benjaminのコメントを参考にして、コメントをキャッチして、投稿を編集し、さらに追加しました。 withステートメントとcatchステートメントの両方は、それぞれのブロックに変数を導入します。これブロックスコープです。 これらの変数は、渡されたオブジェクトのプロパティにエイリアスされます。

 //chrome (v8)

 var a = { 'test1':'test1val' }
 test1   // error not defined
 with (a) { var test1 = 'replaced' }
 test1   // undefined
 a       // a.test1 = 'replaced'

編集:明白な例:

test1はwithブロックにスコープが設定されていますが、a.test1にはエイリアスが設定されています。 'Var test1'は、変数aのプロパティでない限り、上位変数(関数またはグローバル)に新しい変数test1を作成します。

Yikes! 'with'を使うことに注意してください。 - 変数が関数ですでに定義されている場合は、変数varがnoopと同じように、オブジェクトからインポートされた名前に関してはnoopです。 すでに定義されている名前にちょっと頭を付けると、これはずっと安全になります。 私は個人的にこれのために使用されません。


グローバルに宣言された変数には、グローバルスコープがあります。 関数内で宣言された変数は、その関数にスコープされ、同じ名前のグローバル変数がシャドウされます。

(本当のJavaScriptプログラマが他の答えで指摘できるような微妙な点があると確信しています。特に、 このページにはいつでも正確な意味があります。しかし。)


私の理解は、3つのスコープがあることです。グローバルスコープは、グローバルに利用可能です。ブロックに関係なく機能全体で使用可能なローカルスコープ。ブロックスコープは、使用されたブロック、ステートメント、または式でのみ使用できます。グローバルスコープとローカルスコープは、関数または外部のいずれかでキーワード 'var'で示され、ブロックスコープはキーワード 'let'で示されます。

グローバルスコープとローカルスコープしかないと思う人には、MozillaがJSのブロックスコープのニュアンスを説明するページ全体を持つ理由を説明してください。

let


私はあなたが勉強するための例をたくさん与えることができる最高のことを考えます。 Javascriptのプログラマーは、スコープをどれだけうまく理解しているかによって、実際にランク付けされています。 時には、直感に反することもあります。

  1. グローバルスコープ変数

    // global scope
    var a = 1;
    
    function one() {
      alert(a); // alerts '1'
    }
    
  2. ローカルスコープ

    // global scope
    var a = 1;
    
    function two(a) { // passing (a) makes it local scope
      alert(a); // alerts the given argument, not the global value of '1'
    }
    
    // local scope again
    function three() {
      var a = 3;
      alert(a); // alerts '3'
    }
    
  3. 中級JavaScriptのブロックスコープのようなものはありません (ES5; ES6ではlet導入let

    a。

    var a = 1;
    
    function four() {
      if (true) {
        var a = 4;
      }
    
      alert(a); // alerts '4', not the global value of '1'
    }
    

    b。

    var a = 1;
    
    function one() {
      if (true) {
        let a = 4;
      }
    
      alert(a); // alerts '1' because the 'let' keyword uses block scoping
    }
    
  4. 中級オブジェクトのプロパティ

    var a = 1;
    
    function Five() {
      this.a = 5;
    }
    
    alert(new Five().a); // alerts '5'
    
  5. 上級者閉鎖

    var a = 1;
    
    var six = (function() {
      var a = 6;
    
      return function() {
        // JavaScript "closure" means I have access to 'a' in here,
        // because it is defined in the function in which I was defined.
        alert(a); // alerts '6'
      };
    })();
    
  6. 上級者プロトタイプベースのスコープ解決

    var a = 1;
    
    function seven() {
      this.a = 7;
    }
    
    // [object].prototype.property loses to
    // [object].property in the lookup chain. For example...
    
    // Won't get reached, because 'a' is set in the constructor above.
    seven.prototype.a = -1;
    
    // Will get reached, even though 'b' is NOT set in the constructor.
    seven.prototype.b = 8;
    
    alert(new seven().a); // alerts '7'
    alert(new seven().b); // alerts '8'
    
  7. グローバル+ローカル余分な複雑なケース

    var x = 5;
    
    (function () {
        console.log(x);
        var x = 10;
        console.log(x); 
    })();
    

    JavaScriptは常に変数宣言(初期化ではない)をスコープの先頭に移動するので、コードは次のようになります。

    var x = 5;
    
    (function () {
        var x;
        console.log(x);
        x = 10;
        console.log(x); 
    })();
    
  8. Catch節スコープ変数

    var e = 5;
    console.log(e);
    try {
        throw 6;
    } catch (e) {
        console.log(e);
    }
    console.log(e);
    

    これで5,6,5が印刷されます。 catch節の内部では、グローバル変数とローカル変数をシャドウします。 しかし、この特別なスコープはキャッチされた変数に対してのみです。 あなたがvar f;を書くならばvar f; catch節の中で、try-catchブロックの前後に定義したのとまったく同じです。


JSには機能スコープしかありません。 スコープをブロックしないでください! 何が巻いているのかを見ることができます。

var global_variable = "global_variable";
var hoisting_variable = "global_hoist";

// Global variables printed
console.log("global_scope: - global_variable: " + global_variable);
console.log("global_scope: - hoisting_variable: " + hoisting_variable);

if (true) {
    // The variable block will be global, on true condition.
    var block = "block";
}
console.log("global_scope: - block: " + block);

function local_function() {
    var local_variable = "local_variable";
    console.log("local_scope: - local_variable: " + local_variable);
    console.log("local_scope: - global_variable: " + global_variable);
    console.log("local_scope: - block: " + block);
    // The hoisting_variable is undefined at the moment.
    console.log("local_scope: - hoisting_variable: " + hoisting_variable);

    var hoisting_variable = "local_hoist";
    // The hoisting_variable is now set as a local one.
    console.log("local_scope: - hoisting_variable: " + hoisting_variable);
}

local_function();

// No variable in a separate function is visible into the global scope.
console.log("global_scope: - local_variable: " + local_variable);

JavaScriptには2種類のスコープがあります。

  1. グローバルスコープグローバルスコープで発表される変数は、プログラム内のどこでも非常にスムーズに使用できます。例えば:

    var carName = " BMW";
    
    // code here can use carName
    
    function myFunction() {
         // code here can use carName 
    }
    
  2. 機能スコープまたはローカルスコープ:このスコープで宣言された変数は、それ自身の関数でのみ使用できます。例えば:

    // code here can not use carName
    function myFunction() {
       var carName = "BMW";
       // code here can use carName
    }
    

JavaScriptには2種類のスコープしかありません:

  1. グローバルスコープ :グローバルは、ウィンドウレベルのスコープに過ぎません。ここでは、アプリケーション全体に存在する変数です。
  2. Functional Scopevarキーワードを持つ関数内で宣言された変数は機能スコープを持ちます。

関数が呼び出されるたびに、可変スコープオブジェクトが作成され(スコープチェーンに含まれます)、その後にJavaScriptの変数が続きます。

        a = "global";
         function outer(){ 
              b = "local";
              console.log(a+b); //"globallocal"
         }
outer();

スコープチェーン - >

  1. ウィンドウレベル - outerouter関数はスコープチェーンのトップレベルにあります。
  2. 新しいvariable scope object (スコープチェーンに含まれている)と呼ばれる外部関数が変数b内部に追加したとき。

変数a必要なときには、最初に最も近い変数スコープを検索し、変数がそこに存在しない場合は、可変スコープチェーンの次のオブジェクトに移動します。この場合、ウィンドウレベルです。


グローバル:関数の外で宣言された変数

Local:関数内で宣言された変数で、そのスコープ内でのみ呼び出すことができます


現代Js、ES6 +、 ' const 'と ' let '

他のほとんどの主要言語と同様に、作成する変数ごとにブロックスコープを使用する必要があります。 var時代遅れです。 これにより、コードをより安全に保守しやすくなります。

const95%のケースで使用する必要があります。 可変参照が変更できないようにします。 配列、オブジェクト、およびDOMノードのプロパティは変更でき、おそらくconstはずです。

letは再割り当てが必要な変数に使用する必要があります。 これにはforループが含まれます。 初期化を超えて値を変更した場合は、 let使用letます。

ブロックスコープとは、変数が宣言されている括弧内でのみ使用可能であることを意味します。 これは、スコープ内で作成された匿名関数を含む内部スコープにまで及ぶ。


スコープは、宣言されたすべての識別子(変数)のルックアップリストであり、現在実行中のコードからどのようにアクセスできるかについての厳密な規則のセットを強制します。 このルックアップは、LHS(左手側)参照である変数に割り当てる目的のために、またはRHS(右手側)参照であるその値を検索するために使用することができる。 これらのルックアップは、コードをコンパイルして実行するときにJavaScriptエンジンが内部的に行っているものです。

だからこのような観点から、カイル・シンプソンのスコープとクローズの電子ブックで見つけた画像が役に立ちそうです:

彼の電子ブックから引用する:

このビルディングは、プログラムのネストスコープのルールセットを表しています。 建物の1階は、どこにいても現在実行中のスコープを表します。 建物のトップレベルはグローバルスコープです。 現在のフロアを見て、見つからない場合は、エレベーターを次のフロアに移動し、そこを見て、次に見るなどで、LHSとRHSの参照を解決します。 最上階(グローバルスコープ)に到達すると、探しているものを見つけるか、そうでないものを見つけることができます。 しかし、あなたは無関係に止める必要があります。

注目すべき点の1つは、「スコープルックアップは最初の一致が見つかると停止します」。

この「スコープレベル」の考え方は、ネストされた関数でルックアップされている場合、新しく作成されたスコープで「this」を変更できる理由を説明しています。 ここでは、これらのすべての詳細に入るリンクです.JavaScriptのスコープについて知りたいことすべて


EcmaScript5には主に2つのスコープ、つまりローカルスコープグローバルスコープがありますが、EcmaScript6には主に3つのスコープ、ローカルスコープ、グローバルスコープ、ブロックスコープと呼ばれる新しいスコープがあります

ブロックスコープの例は次のとおりです。

for ( let i = 0; i < 10; i++)
{
 statement1...
statement2...// inside this scope we can access the value of i, if we want to access the value of i outside for loop it will give undefined.
}

コードを実行します。 これがスコープについての考えを与えることを願って

Name = 'global data';
document.Name = 'current document data';
(function(window,document){
var Name = 'local data';
var myObj = {
    Name: 'object data',
    f: function(){
        alert(this.Name);
    }
};

myObj.newFun = function(){
    alert(this.Name);
}

function testFun(){
    alert("Window Scope : " + window.Name + 
          "\nLocal Scope : " + Name + 
          "\nObject Scope : " + this.Name + 
          "\nCurrent document Scope : " + document.Name
         );
}


testFun.call(myObj);
})(window,document);

私は、JavaScriptを初めて使う多くの人が、言語でデフォルトで継承が利用可能であり、関数スコープがこれまでの唯一のスコープであることを理解するのに問題があることを発見しました。 私は、昨年末に書いた美容院の拡張部を、「ジャグレティー」と呼んだ。 フィーチャカラーはコード内のスコープを機能させ、常にそのスコープで宣言されたすべての変数にカラーを関連付けます。 あるスコープの色を持つ変数が別のスコープで使用されている場合、クロージャは視覚的に示されます。

次の場所で機能を試してください:

デモをご覧ください:

コードを表示する場所:

現在、この機能は深さ16のネストされた関数をサポートしていますが、現在はグローバル変数に色付けされていません。


この興味深い例を試してみてください。以下の例では、aが0で初期化された数値だった場合、0と1が表示されます。aはオブジェクトであり、javascriptはf1にaのコピーではなくaのポインタを渡します。その結果、同じ警告が両方の時間に発生します。

var a = new Date();
function f1(b)
{
    b.setDate(b.getDate()+1);
    alert(b.getDate());
}
f1(a);
alert(a.getDate());

"Javascript 1.7"(JavascriptへのMozillaの拡張)では、 letステートメントでブロックスコープ変数を宣言することもできます:

 var a = 4;
 let (a = 3) {
   alert(a); // 3
 }
 alert(a);   // 4




var