この記事では、javascriptに関する関連知識を提供します。主に、JS エンジンが JS コードを実行する方法に関連する問題を紹介します。JS エンジンが JS コードを実行するときも、上から下に実行されます。以下では字句解析、構文解析、意味解析などの処理が行われ、コード解析が完了するとASTが生成されます。
関連する推奨事項:javascript チュートリアル
おそらく「実行環境」、「スコープ」、「プロトタイプ」(チェーン) という言葉をよく耳にします。 )」、「実行コンテキスト」など、何を説明していますか?
js は型指定が弱い言語であり、変数の型は実行時にのみ決定されることがわかっています。 JS エンジンは、JS コードを実行する際に、字句解析、文法解析、意味解析などの処理を上から下に実行します。コードの解析が完了 AST(抽象構文木)を生成し、最終的にASTに基づいてCPUが実行できる機械語コードを生成して実行します。
さらに、JS エンジンはコードの実行時に他の処理も実行します。たとえば、V8 には 2 つのステージがあります:
これ ここでは、「実行コンテキスト」と「スコープ チェーン」という 2 つの概念を導入します。
上記のことから、js コードが実行可能コードの一部を実行すると、対応する実行コンテキストが作成されることがわかります。
まず、js の実行コードに相当する概念として「実行環境」、つまりグローバル環境、関数環境、eval
があります。
次に、各実行コンテキストには 3 つの重要なプロパティがあります。
2 つのコードを見てみましょう:
var JavaScript エンジンが JS コードを実行する方法についての深い理解="global JavaScript エンジンが JS コードを実行する方法についての深い理解";function checkJavaScript エンジンが JS コードを実行する方法についての深い理解(){ var JavaScript エンジンが JS コードを実行する方法についての深い理解="local JavaScript エンジンが JS コードを実行する方法についての深い理解"; function f(){ return JavaScript エンジンが JS コードを実行する方法についての深い理解; } return f();}checkJavaScript エンジンが JS コードを実行する方法についての深い理解();
var JavaScript エンジンが JS コードを実行する方法についての深い理解="global JavaScript エンジンが JS コードを実行する方法についての深い理解";function checkJavaScript エンジンが JS コードを実行する方法についての深い理解(){ var JavaScript エンジンが JS コードを実行する方法についての深い理解="local JavaScript エンジンが JS コードを実行する方法についての深い理解"; function f(){ return JavaScript エンジンが JS コードを実行する方法についての深い理解; } return f;}checkJavaScript エンジンが JS コードを実行する方法についての深い理解()();
何を出力しますか? ############なぜ?答えは、実行コンテキスト スタックが異なるということです。
実行コードを実行する際には事前の準備が行われますが、ここでの「準備」を専門的には「実行コンテキスト」と呼びます。しかし、関数などの実行可能コードが増加するにつれて、非常に多くの実行コンテキストをどのように管理すればよいでしょうか?そこで、JS エンジンは実行コンテキスト スタックの概念を作成しました。
配列を完全に使用してその動作をシミュレートできます (スタックの一番下には常にグローバル実行コンテキスト globalContext があります)
最初に EStack を定義しますそして最初のコード スニペットをシミュレートします:EStack=[globalContext];ログイン後にコピー
EStack.push(functionContext);EStack.push( functionContext);EStack.pop();EStack.pop();
そして 2 番目のコード スニペットは次のようになります:
EStack.push(functionContext);EStack.pop();EStack.push( functionContext);EStack.pop();
その理由は、最初に「クロージャ」の概念を学ぶ必要があるかもしれないからです。
さて、「フロントエンドのモジュール化」において「長期的なデータ保存」を実現するにはどうすればよいでしょうか?キャッシュ?いいえ。閉鎖!
まず、スコープとは、変数が定義されるプログラム内の領域を指します。スコープは変数の検索方法を指定し、現在実行中のコードの変数へのアクセス権を決定します。
JavaScript スコープとスコープ チェーン
動的スコープ
の 2 種類があります。JS で使用される静的スコープは「レキシカル スコープ」とも呼ばれます。関数のスコープは、関数の定義時に決定されます。上記のことから、字句スコープ内の変数は、コンパイル プロセス中に特定のスコープを持つことになります。このスコープは「現在の実行コンテキスト」です。 ES5 以降では、スコープの代わりに「レキシカル環境」を使用して実行コンテキストを記述します。字句環境は 2 つのメンバーで構成されます:
var JavaScript エンジンが JS コードを実行する方法についての深い理解=1;function foo(){ console.log(JavaScript エンジンが JS コードを実行する方法についての深い理解);}function bar(){ var JavaScript エンジンが JS コードを実行する方法についての深い理解=2; foo();}bar();
foo() 関数を実行します。まず、foo 関数内にローカル変数値があるかどうかを確認します。そうでない場合、は定義時の位置、つまり JavaScript エンジンが JS コードを実行する方法についての深い理解=1 に基づいて上位層のコード
もちろん、これはそれほど単純で要約できるものではなく、実行コンテキストの観点から分析することもできます。
上面我们说了词法环境(作用域)的两个组成。再结合执行上下文,我们不难发现:通过外部词法环境的引用,作用域可以顺着栈层层拓展,建立起从当前环境向外延伸的一条链式结构。
再来看一个例子:
function foo(){ console.dir(bar); var a=1; function bar(){ a=2; }}console.dir(foo);foo();
由静态作用域,全局函数foo创建了一个自身对象的[[JavaScript エンジンが JS コードを実行する方法についての深い理解]]
属性
foo[[JavaScript エンジンが JS コードを実行する方法についての深い理解]]=[globalContext];
而当我们执行foo()时,也会先后进入foo函数的定义期和执行期。在foo函数的定义期时,函数bar的[[JavaScript エンジンが JS コードを実行する方法についての深い理解]]
将会包含全局内置JavaScript エンジンが JS コードを実行する方法についての深い理解和foo的内置JavaScript エンジンが JS コードを実行する方法についての深い理解
bar[[JavaScript エンジンが JS コードを実行する方法についての深い理解]]=[fooContext,globalContext];
这证明了这一点:“JS会通过外部词法环境引用来创建变量对象的一个作用域链,从而保证对执行环境有权访问的变量和函数的有序访问。”
让我们再回头看看执行上下文中的那道题,在前面我们说了它们有什么不同,这里说下为什么它们相同地打印了“local JavaScript エンジンが JS コードを実行する方法についての深い理解”:还是那句话“JS采用的是词法作用域,函数的作用域取决于函数创建的位置” —— JS函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数 f() 定义在这个作用域链里,其中的变量JavaScript エンジンが JS コードを実行する方法についての深い理解一定是指局部变量,不管何时何地执行 f() ,这种绑定在执行 f() 时依然有效。
当某个变量无法在自身词法环境记录中找到时,可以根据外部词法环境引用向外层进行寻找,直到最外层的词法环境中外部词法环境引用为null
。
与此相似的是“对象中基于原型链的查找”:
__proto__
为null)为止它们的区别也显而易见:原型链是通过 prototype 属性建立对象继承的链接;而作用域链是指内部函数能访问到外部函数的闭包。不管直接还是间接,所有函数的作用域链最终都链接到全局上下文。
相关推荐:javascript学习教程
以上がJavaScript エンジンが JS コードを実行する方法についての深い理解の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。