jaavscript関数と変数の割り当て

4964 ワード

出典は有名なここですです.自分はこの面で練習しなければならないと感じています.
javascriptでは、すべての変数と関数がLexicalEnvironmentという特殊な内部オブジェクトの属性です.ブラウザの最上階のLexicalEnvironmentwindowで、 とも呼ばれます.
グローバル変数の実装
関数が実行されるときには、 段階の1があります.まず、解凍器は、メインコードストリームから関数宣言をすべて探し出し、そこから関数を生成し、windowオブジェクトに入れます.
var a = 5;
function f(arg) { alert('f:'+arg) }
var g = function(arg) { alert('g:'+arg) }
このステップでは、ブラウザはfunction fを見つけ、関数を生成し、window.fとして保存する.//1.関数宣言は、コードが実行される前に初期化される//2.だから、最初の行のコードの前にwindow={f:function}がある.
var a = 5;
function f(arg) { alert('f:'+arg) }; // <--    
var g = function(arg) { alert('g:'+arg) }
副作用とは、fは声明の前に呼び出されることができるということです.
f();
function f() { alert('ok') }
2.その後、解釈器は変数宣言を検索し、対応するwindow属性を生成します.このステップは変数に値を与えませんでした.すべての変数値はundefinedです.
// 1.           
// window = {f:function}

// 2.    window        
// window = {f:function, a:undefined, b:undefined}

// var a = 5; <-- var
function f(arg) { alert('f:'+arg) }
var g = function(arg) { alert('g:'+arg) } // <-- var
gの値は関数式ですが、解釈器はこれを気にしません.変数を生成しますが、値を与えません.
まとめ:
1.               ,                  .
2.     undefined
3.         ,            
副作用:同じ名前の関数と変数を生成できませんでした.
3.関数の運転を開始します.変数や関数が読み取られると、解釈器はwindowからそれらを取得します.
<!-- lang: js -->
alert("a" in window); // true,   window.a  
alert(a); // undefined,       
alert(f); // function,      
alert(g); // undefined,     

var a = 5;  

function f(); { /*...*/ } 
var g = function(); { /*...*/ }
4.賦値の後、aの値は5、gは関数です.下のコードはalertを移動しました.上のコードと違いますので注意してください.
var a = 5; 
var g = function(); { /*...*/ }
alert(a); // 5
alert(g); // function
変数がvarで宣言されていない場合、初期化フェーズはありません.
alert("b" in window); // false, there is no window.b
alert(b); // error, b is not defined
b = 5;
但し、赋価実行後、bは変数window.bとなり、var宣言を行うのと同じである.
b = 5;
alert("b" in window); // true, there is window.b = 5
問題の答えは
if ("a" in window) {
var a = 1;
}
alert(a);
答えは1です.コードを追跡してみましょう.
1.初期化段階、window.a生成
// window = {a:undefined};
if ("a" in window) {
var a = 1;
}
alert(a);
2.「a」in window値は本当です.
// window = {a:undefined};
if (true) {
var a = 1;
}
alert(a);
したがって、実行後のaの値は1です.
問題の答えは
if ("a" in window) {
a = 1;
}
alert(a);
答えは「Errar:no such variable」で、"a" in windowをチェックすると変数aが存在しません.if分岐は実行されません.
関数
関数実行時には、新しいLexical Environmentが作成され、パラメータ、変数、ネストされた関数宣言が追加されます.windowとは異なり、関数のLexicalEnvironmentは直接アクセスできません.
以下の関数の実行の詳細を考えましょう.
function sayHi(name) {
var phrase = "Hi, " + name;
alert(phrase);
}
sayHi('John');
インタプリタが関数の実行を開始する準備をすると、最初の行のコードが実行される前に、氏は空になったLexicalEnvironmentにパラメータ、局所変数、および内部関数を追加します.
function sayHi(name) {
// LexicalEnvironment = { name: 'John', phrase: undefined }
var phrase = "Hi, " + name;
alert(phrase);
}
sayHi('John');
したがって、パラメータは最初から与えられています.変数はありません.
2.関数が実行されている場合は、最終的な割り当てを行います.
内部変数の割当値は、LexicalEnvironmentにおける対応する属性が新たな値を得ることを意味する.
したがって、phrase = "Hi, "+nameLexicalEnvironmentを変更した.
最後の行alert(phrase)は、LexicalEnvironmentのphaseの値を検索して出力する.
特性説明ECMA 262は、2つのオブジェクトを事実上規定しています.1つ目はVariableEnvironmentオブジェクトで、関数と変数によって構成されています.関数宣言によって生成された後の指向は可変ではありません.もう1つはLexicalEnvironmentオブジェクトで、特性はVariableEnvironmentと似ています.コードの制御フローによって変更されるかもしれません.より詳細な説明はECMA-2662の規定で見つけられます.javascriptで実行します.これらの2つのオブジェクトは1つに統合することができます.したがって、これらの詳細は、統一的にLexicalEnvironmentを使用することを回避します.
ブロックレベルのスコープが存在しません.
下の二つのコードは実は区別がありません.
var i = 1;
{
i = 5;
}

i = 1;
{
var i = 5;
}
この二つのコードの中で、変数は事前に実行前に宣言しました.他のJAVA、Cなどの言語と違って、循環内の変数は循環外でも有効です.
javascriptは関数のスコープです.
for(var i=0; i<5; i++) { }
alert(i); // 5,          
ループで変数を定義するのは便利ですが、ローカル変数は生成されません.
function test() {
alert(window);
var window = 5;
}
test();
変数宣言は、関数の前処理段階で存在し、windowは、alertによって前にすでに局所変数LexicalEnvironment = {window: undefined}であるため、関数がalertに実行されると、変数windowは既に存在し、undefined.
var value = 0;
function f() { 
if (1) {
value = 'yes';
}
else {
var value = 'no';
}
alert(value);
}
f();
関数前処理段階では、変数宣言はLexicalEnvironmentの属性として機能が実行されると、value='yes'は部分変数に値を割り当て、最終的な出力値はyesです.