この記事では、JavaScript の事前解析と関連テクニックについて例を示して説明します。参考のために皆さんと共有してください。詳細は次のとおりです:
変数
同様に、これら 2 つの小さな例のエラー比較のヒントから始めます。
alert(y1); //代码段1 var y1 = 'dddd'; alert(y2); //代码段2 // alert(typeof y2); y2 = 'xxxxx';
最初に考えてください。なぜ一方は未定義のプロンプトを表示し、もう一方は未定義変数のエラーをスローするのかを考えてください。 。まず JavaScript の解析プロセスを見てみましょう。
JavaScript はプロセスを実行する前にイベント「事前解析」を実行します。解析エンジンは、ブロック レベルですべての var 変数の作成を実行し、それらに初期値 (未定義) を与えます。このようにすると、最初の例で unknown がポップアップ表示される理由は明らかです。
つまり、コードの最初の部分は実際には
と同等です。var y1; alert(typeof y1); //很自然,它此时值为undefined y1 = 'dddd';
では、コードの 2 番目の部分が再びエラーをスローするのはなぜでしょうか。これはもう「事前解析」段階ではありません (ここでは、ブラウザがスクリプト タグに遭遇したときに 2 つのことだけを行うと仮定します。つまり、事前解析です。と実行。実際にはこれら 2 つだけではありません) が、実行段階でエラーがスローされる理由は、js が実行セクションの状態 (解析前の段階) で y2 のステータスを知らないためです。 y2) に関する情報は取得されません。もちろん、未定義のエラー情報がスローされます。これには別の問題が伴います。js は型付けが弱い言語で、変数は定義しなくても使用できるのに、なぜここで定義エラーがスローされるのでしょうか。
すべての出来事には理由があります。JavaScript には、変数の読み取りと書き込みが不均一であるなど、独自の多くの奇妙な特性が常にあります。未定義の変数は書き込みのみ可能であり、読み取りはできません。書き込み可能とは何ですか? 誰もがこの書き方に精通しています:
y2 = 'exam'; //在没出现它的定义操作之前(即在它还没有自己的scope之前)该操作会将这段代码认为是定义一个全局变量,在window上注册一个属性y2,并赋值为exam
しかし、それを読み込むと、js エンジンはそれに関する関連情報を見つけることができないため、自分の気の向くままに動作し、容赦なく未定義のエラーをスローします。これが js のゲームのルールです。しかし、なぜその型を取得できるのでしょうか? js がオブジェクトに対してどのように動作するかを思い出してください。オブジェクトの存在しないプロパティとタイプにアクセスすると、未定義というプロンプトが表示されます (これは現在ウィンドウ オブジェクトのプロパティであるため)。
もう 1 つの注意点: 変数の読み取りと書き込みは同等ではありません。この機能が存在しない場合は、すべてのオブジェクトのプロパティが読み取られます。 、未定義のプロンプトが表示されます。
結論
これが私の考えの結果です: 変数とオブジェクトの書き込み操作には類似点があります。しかし、それぞれの読み取り操作には独自のルールが存在するため、上記の問題が発生します。
このようにして、次の質問に対する答えは簡単になるはずです。
if (!('a' in window)) { var a = 1; } alert(a);
関数
拡張子は関数です。JavaScript の事前解析には、var 変数の事前定義に加えて、関数の定義の抽出も含まれることを思い出してください。関数はスクリプトのどこにでも定義でき、どこでも呼び出すことができます。以前のものに限定されません。
しかし、関数を定義する方法には、var メソッドを使用して関数を宣言するリテラル定義と呼ばれるメソッドが含まれています。
を参照してください。alert(typeof y3); //结果? var y3 = function (){ console.log('1'); }
この規則を覚えておいてください。なぜなら、呼び出しはステートメントの後に現れる必要があります。上記を理解していれば、ここでの答えはすでに明らかです。 javascript エンジンは、var を事前解析するときに初期値として unknown を与えます。このように、宣言前にこれを呼び出した場合、javascript エンジンはまだ真の値を取得していないため、当然のことながら「xxx は関数ではありません」と報告します。 " 違います。これにより、両方が関数宣言である理由も明確になりますが、一方は宣言と呼び出しの順序に関連しており、もう一方にはそのような制約がありません。
結論
これは関数であり、js の実行と動的変更の結果であり、変数の事前解析ルールに従います (上記の警告の際、リテラル関数の情報は取得されませんでした)。
この2つが混ざったらどうなるでしょうか。以下を参照してください。y4 には変数と関数の両方があります。
alert(typeof y4); //结果? function y4(){ console.log('y4') } var y4;
JavaScriptの事前解析における関数の宣言優先度が高いため、y4は当然関数型ですが、y4に値を代入した後(この時点でjsエンジンが実行中です)、jsへの代入操作が行われます。関数の宣言をオーバーライドします。つまり:
alert(typeof y5); var y5 = 'angle'; function y5(){ console.log('ghost'); } alert(y5);
最初のアラート結果は、js 実行プロセスの先頭にあるため function です。 2 回目のアラートでは、その値は 5 に書き換えられています (以下の関数の定義位置に騙されないでください)
js の解析と実行を分けて考えると、突然目が冴え、多くの疑問に対する答えが自然に見えてくることに気づきました。その記事の著者が言ったように、「実行環境とオブジェクトの呼び出しを理解すれば、パッケージ、レキシカルスコープ、スコープチェーンなどの概念は、JS 言語の多くの現象を簡単に解決できます。
今見てみると、信じられないことがたくさんあるこの言語にも、遡ることができる理由がたくさんあります。パラメータをより適切に判断する方法
ここまで議論してきましたが、JavaScript には読み書きにばらつきがあるため、エラーを報告せずにパラメータの判断を回避するにはどうすればよいでしょうか?
例:
if(cusVar){ //这里的判断,是不是存在隐含的问题呢。 }
如何严谨一些呢。
if(window['cusVar']) { //保证它不报错。 //或者这样的判断也是可行的 window.cusVar | typeof cusVar !== 'undefined' //干活咯 }
最后补充又一个小quiz, (理解 预解析与执行的分离)
var y7 = 'test'; function fun1(){ alert(y7); var y7 = 'sex'; } fun1();
更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《JavaScript切换特效与技巧总结》、《JavaScript查找算法技巧总结》、《JavaScript动画特效与技巧汇总》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》
希望本文所述对大家JavaScript程序设计有所帮助。