目次
やはり! 、
var a = 2
3.1 函数会被首先提升,然后才是变量
3.2 函数字面量不会进行函数提升
4.1 变量提升是可以规避的
4.2 小结
ホームページ ウェブフロントエンド jsチュートリアル JavaScript トピック 1: 変数のプロモーションとプリコンパイル

JavaScript トピック 1: 変数のプロモーションとプリコンパイル

Mar 02, 2021 am 09:42 AM
javascript

JavaScript トピック 1: 変数のプロモーションとプリコンパイル

目次

  • まえがき
  • 1. 興味深い現象
  • 2. Jsの事前解析
  • #3. プロモーション間の優先度
  • #4. ES6
  • 最後に書く
  • ## (関連する無料学習の推奨事項:

    javascript ビデオ チュートリアル
  • )

はじめに

この記事は「JavaScript に特化した上級シリーズ」です。 》最初の記事、シリーズ全体には、たとえば次のものが含まれる場合があります:

アンチシェイク スロットリング

フラット化
  • 深いコピーと浅いコピー
  • 配列重複排除
  • ソート
  • およびその他の古典的な特別な知識ポイント。多くの場面での「出現率」が高いことから、
  • 特化アドバンス
  • と名付けられましたが、
googleコンテンツサーチャー

にならないために、「JavaScript特化アドバンスシリーズ」が誕生しました! ! !

1. 興味深い現象JavaScript トピック 1: 変数のプロモーションとプリコンパイル

常識によれば、JavaScript コードは上から下に実行される必要があります。もちろん文字列型を事前に保存するには variable を宣言する必要があります。深遠な真実を理解できたら、次のコードを読んでください。

1.1 私が思った冒頭 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">var str = '123';console.log(str); // 123</pre><div class="contentsignin">ログイン後にコピー</div></div> コードの位置を変えてもう一度見てみましょう:

console.log(str); // undefinedvar str = '123';
ログイン後にコピー
パターンを見つけたようです!! !

最初の 2 つのコードを読んで「深く考えて」みたところ、次のパターンを見つけたように思えました。つまり、現在のコード ブロックの後、変数宣言の前の関数内で、初期化変数を使用すると、正しい値が得られません。

1.2 これは実際に当てはまります

JavaScript トピック 1: 変数のプロモーションとプリコンパイル上記の「結論」を持ってここに来ました

var val = '余光';(function(){
    console.log(val); // 余光})();
ログイン後にコピー
やはり! 、
変数の宣言と初期化の後

イエス様は私が val の値を取得するのを止めることはできません、私は言いました! ! !

次のコードを見たとき、私はすでに動揺しました。この件はおかしいに違いありません。

var val = '余光';(function(){
    console.log(val); // undefined
    var val = '测试';})();
ログイン後にコピー
Ps: 関数の即時実行に関する質問がある場合は、「JavaScript の即時呼び出し関数式の詳細な理解 (IIFE)」~

これを参照するとよいでしょう。・・・怖いです、何ですか、この現象は何が原因で起こるのでしょうか? Jsはどうやって対処してるの?

2. Js の事前解析 JavaScript トピック 1: 変数のプロモーションとプリコンパイル

現在のスコープでは、変数がどこで宣言されているかに関係なく、実行されます。舞台裏 目に見えない動き。 注:

ステートメントのみが「移動」されます。つまり、宣言と代入はある時点で受動的に分離されます。そして、この目に見えない動きは、実際にはコンパイル段階での J の

解析です。

「Do you know JS」の典型的な例を見てみましょう:

name = '余光'; // 未添加关键字(未声明),name为全局变量,,即window.name = '余光'var name; // 再次声明name,此时name未进行初始化,它的值是undefined吗?console.log(name); // ?
ログイン後にコピー
その結果、「残光」が正常に出力され、目に見えない動き##が表示されます。 # Js の事前解析 (コンパイル) 中に発生します。

2.1 コア: 事前解析

この中心的な問題を理解するには、エンジンが JavaScript コードを解釈する前にまずコンパイルすることを確認する必要があります。コンパイル フェーズの一部では、すべての宣言を検索し、それらを適切なスコープに関連付けます。興味のある方は、「JavaScript の変数オブジェクト」と「スコープからスコープチェーンへ」の 2 つの記事を読んでください ~

したがって、このようなことが起こった場合、変数##を含むすべての宣言 # と ## を含む# 関数

は、コードが実行される前に最初に処理されます。
var a = 2
; を見ると、これはステートメントだと思うかもしれません。しかし、JavaScript は実際にはこれを var a; と a = 2; という 2 つの宣言として認識します。

最初の定義ステートメントはコンパイル段階で作成されます。 2 番目の代入ステートメントは、実行フェーズを待って所定の位置に残されます。 つまり、コードは次のように記述されます:

// 我们看到的代码:var name = '余光';
ログイン後にコピー
しかし、Js はそれを次のように解析します:
    // 声明(Declaration)var name; // 声明但未初始化,所以分配 undefined// 初始化(Initialization)name = '余光'; // 初始化(赋值)
    ログイン後にコピー
  • したがって、この概要のコードの一部は次のようになります。
  • var name; // 声明name提到作用域顶部,并被分配了一个undefinedname = '余光'; // 进行初始化操作console.log(name); // '余光'
    ログイン後にコピー
  • 2.2 注: 宣言のみが昇格されます
  • 宣言のみが昇格され、代入やその他のコード ロジックは、コード位置

    。したがって、次の問題が発生します。

    foo();function foo(){
        console.log(name); // undefined
        var name = '余光';}
    ログイン後にコピー
    ログイン後にコピー
    関数はプロモートされており、当然通常どおり実行できますが、変数はプロモートされるように宣言されているだけです。

    2.3 各スコープはプロモートされます
    まだ上記のコード:

    foo();function foo(){
        console.log(name); // undefined
        var name = '余光';}
    ログイン後にコピー
    ログイン後にコピー
    実際、コンパイルすると次のようになります:
    function foo(){
        var name; // 声明
        console.log(name); // undefined
        name = '余光'; // 初始化}foo(); // 函数执行
    ログイン後にコピー

    3. 昇格間の優先順位

    変数

    JavaScript トピック 1: 変数のプロモーションとプリコンパイル関数

    が昇格されることがわかったので、それらはどのように判断するのでしょうか。優先順位は?

    3.1 函数会被首先提升,然后才是变量

    我们分析下面的代码:

    foo();var foo; // 1function foo(){
        console.log('余光');}foo = function(){
        console.log('小李');}
    ログイン後にコピー

    本着函数优先提升的原则,他会被解析成这样:

    function foo(){
        console.log('余光');}foo(); // 余光foo = function(){
        console.log('小李');}
    ログイン後にコピー

    注意,var foo 因为是一个重复声明,且优先级低于函数声明所以它被忽略掉了。

    3.2 函数字面量不会进行函数提升

    最直观的例子,就是在函数字面量前调用该函数:

    foo();var foo = function(){
        console.log(1);}// TypeError: foo is not a function
    ログイン後にコピー

    这段程序中:

    1. 变量标识符foo被提升并分配给所在作用域(在这里是全局作用域),因此在执行foo()时不会导致ReferenceError(),而是会提示你 foo is not a function
    2. 然后就是执行foo,foo此时并没有赋值(注意变量被提升了)。由于对undefined值进行函数调用而导致非法操作,因此抛出TypeError异常。

    四、ES6和小结

    ES6新增了两个命令letconst,用来声明变量,有关它们完整的概念我会在《ES6基础系列》中总结,提起它们,是因为变量提升在它们身上不会存在

    4.1 变量提升是可以规避的

    let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。

    // var 的情况console.log(foo); // 输出undefinedvar foo = 2;// let 的情况console.log(bar); // 报错ReferenceErrorlet bar = 2;
    ログイン後にコピー

    上面代码中,变量foo用var命令声明,会发生变量提升,即脚本开始运行时,变量foo已经存在了,但是没有值,所以会输出undefined。变量bar用let命令声明,不会发生变量提升。这表示在声明它之前,变量bar是不存在的,这时如果用到它,就会抛出一个错误。

    在变量提升上,const和let一样,只在声明所在的块级作用域内有效,也不会变量提升

    4.2 小结
    1. 变量提升:函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部,但变量的初始化不会提升;
    2. 函数提升:函数声明可以被看作是函数的整体被提升到了代码的顶部,但函数字面量表达式并不会引发函数提升;
    3. 函数提升优先与变量提升;
    4. let和const可以有效的规避变量提升

    最后提炼一下:JavaScript引擎并不总是按照代码的顺序来进行解析。在编译阶段,无论作用域中的声明出现在什么地方,都将在代码本身被执行前首先进行处理,这个过程被称为提升。声明本身会被提升,而包括函数表达式的赋值在内的赋值操作并不会提升。

    相关免费学习推荐:javascript(视频)

    以上がJavaScript トピック 1: 変数のプロモーションとプリコンパイルの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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

    ホットAIツール

    Undresser.AI Undress

    Undresser.AI Undress

    リアルなヌード写真を作成する AI 搭載アプリ

    AI Clothes Remover

    AI Clothes Remover

    写真から衣服を削除するオンライン AI ツール。

    Undress AI Tool

    Undress AI Tool

    脱衣画像を無料で

    Clothoff.io

    Clothoff.io

    AI衣類リムーバー

    AI Hentai Generator

    AI Hentai Generator

    AIヘンタイを無料で生成します。

    ホットツール

    メモ帳++7.3.1

    メモ帳++7.3.1

    使いやすく無料のコードエディター

    SublimeText3 中国語版

    SublimeText3 中国語版

    中国語版、とても使いやすい

    ゼンドスタジオ 13.0.1

    ゼンドスタジオ 13.0.1

    強力な PHP 統合開発環境

    ドリームウィーバー CS6

    ドリームウィーバー CS6

    ビジュアル Web 開発ツール

    SublimeText3 Mac版

    SublimeText3 Mac版

    神レベルのコード編集ソフト(SublimeText3)

    WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 Dec 17, 2023 pm 02:54 PM

    WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

    WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー Dec 17, 2023 pm 05:30 PM

    WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

    JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 Dec 17, 2023 pm 12:09 PM

    JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と WebSocket テクノロジを使用できます。 WebSocket は、TCP プロトコルをベースとした全二重通信プロトコルで、クライアントとサーバー間のリアルタイム双方向通信を実現します。リアルタイムオンラインオーダーシステムにおいて、ユーザーが料理を選択して注文するとき

    WebSocketとJavaScriptを使ったオンライン予約システムの実装方法 WebSocketとJavaScriptを使ったオンライン予約システムの実装方法 Dec 17, 2023 am 09:39 AM

    WebSocket と JavaScript を使用してオンライン予約システムを実装する方法 今日のデジタル時代では、ますます多くの企業やサービスがオンライン予約機能を提供する必要があります。効率的かつリアルタイムのオンライン予約システムを実装することが重要です。この記事では、WebSocket と JavaScript を使用してオンライン予約システムを実装する方法と、具体的なコード例を紹介します。 1. WebSocket とは何ですか? WebSocket は、単一の TCP 接続における全二重方式です。

    JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 Dec 17, 2023 pm 05:13 PM

    JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

    JavaScriptでinsertBeforeを使用する方法 JavaScriptでinsertBeforeを使用する方法 Nov 24, 2023 am 11:56 AM

    使用法: JavaScript では、insertBefore() メソッドを使用して、DOM ツリーに新しいノードを挿入します。このメソッドには、挿入される新しいノードと参照ノード (つまり、新しいノードが挿入されるノード) の 2 つのパラメータが必要です。

    簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 Jan 05, 2024 pm 06:08 PM

    JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

    JavaScript と WebSocket: 効率的なリアルタイム画像処理システムの構築 JavaScript と WebSocket: 効率的なリアルタイム画像処理システムの構築 Dec 17, 2023 am 08:41 AM

    JavaScript は Web 開発で広く使用されているプログラミング言語であり、WebSocket はリアルタイム通信に使用されるネットワーク プロトコルです。 2 つの強力な機能を組み合わせることで、効率的なリアルタイム画像処理システムを構築できます。この記事では、JavaScript と WebSocket を使用してこのシステムを実装する方法と、具体的なコード例を紹介します。まず、リアルタイム画像処理システムの要件と目標を明確にする必要があります。リアルタイムの画像データを収集できるカメラ デバイスがあるとします。

    See all articles