ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript の var の事前解析と関数宣言の改善_javascript スキルを学ぶためにフォローしてください

JavaScript の var の事前解析と関数宣言の改善_javascript スキルを学ぶためにフォローしてください

WBOY
WBOYオリジナル
2016-05-16 15:32:091153ブラウズ

1. var 変数のプリコンパイル

JavaScript の構文は C、Java、および C# に似ており、総称して C 類似構文と呼ばれます。 C または Java プログラミングの経験がある学生は、「最初に宣言し、後で使用する」というルールに精通している必要があります。宣言されていない変数や関数を使用すると、コンパイル段階でエラーが報告されます。ただし、JavaScript では変数や関数を宣言する前でも使用できます。以下でその謎を詳しく見ていきましょう。

まずコードの一部を見てみましょう:

(function() {
 console.log(noSuchVariable);//ReferenceError: noSuchVariable is not defined
})();

上記のコードを実行すると、すぐにエラーが報告されます。ただし、noSuchVariable 変数がまったく定義されていないため、これはまさに予想どおりです。次のコードを見てみましょう:

(function() {
 console.log(declaredLater); //undefined
 var declaredLater = "Now it's defined!";
 console.log(declaredLater);// "Now it's defined!"
})();

まず、上記のコードは正しいので問題ありません。しかし、なぜエラーが報告されないのでしょうか? declaredLater 変数は呼び出しステートメントの後に定義されていますか?出力が未定義なのはなぜですか?

これは実際には JavaScript パーサーによって発生します。パーサーは、現在のスコープで宣言されたすべての変数と関数をスコープの先頭に配置します。ただし、変数の宣言のみがスコープの先頭に進みます。そのまま残されています。上記のコードは実際にはパーサーからは次のように見えます:

(function() {
 var declaredLater; //声明被提前到作用域开始处了!
 console.log(declaredLater); // undefined
 declaredLater = "Now it's defined!"; //赋值操作还在原地!
 console.log(declaredLater);//"Now it's defined!"
})();

これが、上記のコードが例外を報告しない理由です。変数と関数が「高度」になった後、JavaScript 構文の定義に従って、declaredLater 変数は実際には宣言されたが割り当てられていない変数に自動的に割り当てられます。そのため、最初の出力は実行されます。 declaredLater 変数の値は未定義です。後で、declaredLater 変数に値を割り当てたので、変数を 2 回目に出力すると、「定義されました」と出力されます。

別の例を見てみましょう:

var name = "Baggins";
(function () {
 console.log("Original name was " + name);// "Original name was undefined"
 var name = "Underhill";
 console.log("New name is " + name);// "New name is Underhill"
})();

上記のコードでは、最初に変数名を宣言しています。本来の目的は、name 変数を初めて出力するときにグローバル スコープで定義された name 変数を出力し、次に関数内でローカルな name 変数を定義することです。グローバル変数をカバーし、最後にローカル変数の値を出力します。ただし、最初の出力結果は期待と完全に一致しません。その理由は、定義したローカル変数がそのスコープ内で「高度」であるためです。つまり、次の形式になります。

var name = "Baggins";
(function () {
 var name; //注意:name 变量被提前了!
 console.log("Original name was " + name);// "Original name was undefined"
 name = "Underhill";
 console.log("New name is " + name);//"New name is Underhill"
})();
JavaScript にはこのような「癖」があるため、常に注意を払うように変数宣言をスコープの先頭に配置することをお勧めします。

2. 関数宣言は「高度」です

先ほどは変数について話しましたが、次は関数について話しましょう。

関数が「高度な」状況には 2 つの状況があります。1 つは関数の宣言で、もう 1 つは関数が値として変数に代入されている状況、つまり関数式です。

まず最初の状況、コードについて話しましょう:

isItHoisted();//"Yes!"
function isItHoisted() { 
 console.log("Yes!");
}
上に示したように、JavaScript インタプリタでは関数宣言の前にそれを使用することができます。つまり、関数宣言は関数名だけでなく、関数定義全体も「高度」です。したがって、上記のコードは正しく実行できます。

2 番目のケース、関数式の形式を見てみましょう。コードから始めましょう:

definitionHoisted();// "Definition hoisted!"
definitionNotHoisted();// TypeError: undefined is not a function
function definitionHoisted() { 
 console.log("Definition hoisted!");
}
var definitionNotHoisted = function () { 
 console.log("Definition not hoisted!");
};
definitionHoisted 関数は最初のタイプに準拠して適切に実行されましたが、その割り当て (つまり関数) は高度ではありませんでした。つまり、これは先ほど説明した変数の「advancement」と完全に一致しており、「advancement」変数のデフォルト値が未定義であるため、報告されるエラーは「型の不一致」に属します。未定義は関数ではないためです。もちろん呼び出すことはできません。

概要
上記の説明をまとめると、次のようになります。

変数の宣言はスコープの先頭に進み、代入はそのまま残ります

関数宣言全体が「高度」です
関数式を使用する場合、変数のみが「高度」になり、関数は「高度」になりません

3. var の副作用

暗黙的なグローバル変数と明示的に定義されたグローバル変数の小さな違いは、削除演算子を使用して変数を未定義のままにできることです。

var を通じて作成されたグローバル変数 (関数の外のプログラムで作成されたもの) は削除できません。

var を使用せずに作成された暗黙的なグローバル変数は (関数内で作成されたかどうかに関係なく) 削除できます。
これは、技術的には、暗黙的なグローバル変数は実際にはグローバル変数ではなく、グローバル オブジェクトのプロパティであることを示しています。属性は delete 演算子を使用して削除できますが、変数は削除できません:

// 定义三个全局变量
var global_var = 1;
global_novar = 2;  // 反面教材
(function () {
 global_fromfunc = 3; // 反面教材
}());

// 试图删除
delete global_var;  // false
delete global_novar; // true
delete global_fromfunc; // true

// 测试该删除
typeof global_var;  // "number"
typeof global_novar; // "undefined"
typeof global_fromfunc; // "undefined"

在ES5严格模式下,未声明的变量(如在前面的代码片段中的两个反面教材)工作时会抛出一个错误。

4、单var形式声明变量

在函数顶部使用单var语句是比较有用的一种形式,其好处在于:

提供了一个单一的地方去寻找功能所需要的所有局部变量
防止变量在定义之前使用的逻辑错误
少代码(类型啊传值啊单线完成)
单var形式长得就像下面这个样子:

function func() {
 var a = 1,
  b = 2,
  sum = a + b,
  myobject = {},
  i,
  j;
 // function body...
}

您可以使用一个var语句声明多个变量,并以逗号分隔。像这种初始化变量同时初始化值的做法是很好的。这样子可以防止逻辑错误(所有未初始化但声明的变量的初始值是undefined)和增加代码的可读性。在你看到代码后,你可以根据初始化的值知道这些变量大致的用途。

以上就是针对javascript的var预解析与函数声明提升的学习内容,希望对大家的学习有所帮助。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。