ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript の変数と字句環境を段階的に理解します。

JavaScript の変数と字句環境を段階的に理解します。

青灯夜游
青灯夜游転載
2020-07-07 15:54:273398ブラウズ

JavaScript の変数と字句環境を段階的に理解します。

実のところ、JavaScript の中核で重要なことは、代入の構造化、展開構文、残りのパラメータなど、古いバージョンから拡張された高度な構文ではないと思います (そうですね。 . 確かに非常に666ですが)、これらをうまく使用することは実際には 変数の理解に基づいています (人々は左辺値と右辺値の違いを知らないことがよくあります)。 Javascript は、変数とは何かを理解するという最も基本的なことから始める必要があります。

この記事は実際には完全に基礎的なものではありませんが、依然として Javascript の 一定の理解、少なくとも オブジェクト の一定の理解に基づいています。はじめましょう。

変数とデータ

変数とは何ですか?

質問に対する答えが単純であればあるほど、それはより驚くべきものになります。ほとんどの人の答えは

value に関連しています。実際、変数は # が格納される記憶域です。 ## プログラムは動作可能です (メモリ空間という用語) 、JavaScript プログラムの実行中に、コードやデータなど、必要なものをすべて保存できる記憶領域 (メモリ空間という用語) が保存されます。すると、変数に格納されているデータは、元型(基本型と同じ)と参照型の2つに大別でき、変数から取り出したデータがそれです。変数 に値 を代入すると、その値は再びデータになります。 JavaScript は他の言語と似ています。変数も実際に存在するように宣言する必要があります。宣言された変数は インスタンス化

と呼ばれます。変数に値が代入されるとき (デフォルトは未定義)インスタンス化されているが初期化されていない

変数 は、uninitialized 状態にあります。 例:

let a = a ;         // (*)
console.log(a);
// ReferenceError: can't access lexical declaration `a' before initialization
はエラー ((*) マークの位置) を完全に報告し、

この変数はこれなしでは使用できないことを示します。初期化

。これは、C などの低レベル変数とは異なります。実際、この現象は Javascript では非常に派手な名前が付けられています:

Temporary Dead Zone 理由については、いくつかの章で説明します。 (変数の宣言にも名前が必要であることを書き忘れていました。この用語は識別子と呼ばれます。付けなくても何も影響しないと思います...) しかし、JavaScript のもう 1 つの特別な点は、var

で宣言された変数を

自動的に初期化できることです。また、JavaScript は、

で宣言された変数に未定義の値を自動的に割り当てます。変数

例:

var a = a;console.log(a);    // undefined.
ほら、これらは明らかに似ていますが、結果はまったく異なります。 しかし、実際には役に立ちません。次のコードを参照してください: <pre class="brush:php;toolbar:false">var a = a;console.log(a+2);   // NaN</pre>結果は
NaN であり、これはまったく望ましくない結果です。

数学的計算が失敗した場合、
JavaScript は、

NaN

で表される 非数値の結果を返します。しかし、さらに興味深いのは、typeof を使用して NaN を検証すると、次のようなタイプになります: <pre class="brush:php;toolbar:false">typeof NaN ;      // number</pre> によって、この TMD が ## であることがわかります。 #数値番号JavaScript には不可解な点がたくさんありますが、JavaScript をからかうのはやめて、真剣に勉強し始めるべきです。

型とストレージ

JavaScript には、次のように、合計 7 つのプリミティブ型と 1 つの参照型があります。 # #元の型

1、数値2、文字列3、ブール値

4、シンボル

    5、bigint
  • 6、未定義

    7、null

    参照型:

    object

    (ここでは小文字を使用しています。

    typeof

    は小文字を返します)

    ここでは理解する必要があることだけを紹介します。具体的な使用方法については他にも資料があるため、詳細については説明しません。ただし、
  • typeof
  • について追加すべき点が 1 つあります。それは、

    null

  • function
の場合、結果は次のようになります:

function sayHello(){
     console.log('hello the world');
 }
 console.log(typeof sayHello);  // function
 console.log(typeof null);      // object
...関数の場合、それは実際に返されるのは「関数」であり、ある意味とても便利ですが、オブジェクトをnull値に戻すのは一長一短としか言いようがありません。
変数についての理解を深める方法は、変数が根底でどのように機能するかを理解することだと思います。実際、特に目立った点はなく、元の値は メモリ スタック領域 に直接配置され、参照型の値は メモリ ヒープ領域 (これが実際のストレージ) に配置されます。領域の場所); (定数の場合、プール

に配置され、スタック領域の一部であるようです)。通常、変数の値は

メモリスタック領域

から直接取得しますが、参照型の値はメモリヒープに配置されるのでどうすればよいでしょうか? 参照型値へのアクセス: 1. 参照型変数は、メモリ スタックにポインタを保存します#2. このポインタは、 # に使用されるメモリ アドレスです。 ##メモリヒープ内の記憶領域を参照3.型値にアクセスする場合

4、会通过指针找到内存堆中的存储区,然后从中获取值。

例如:

  var first  = {
      name:'hahei...'
  }
  var gggiii=111222;

映射图如下:

JavaScript の変数と字句環境を段階的に理解します。

注意:此处我用 ref. first表示  存储区的引用 , 因为虽然保存的尽管是指针,但是在访问这个值时,会进行二次解析(即通过这个指针找到存储区), 而不是直接返回这个指针的具体数据。详细可以参考 C++引用。

初识词法环境

想必各位都已经对什么是作用域了若指掌,但是我还是必须重新提一下作用域标识符的可访问范围,在Javascript中的任何操作,几乎都有作用域的参与。Javascript中使用词法环境决定作用域,在下面我会简单介绍一下。(请注意,这里我没有用变量这个术语,因为解析标识符范围时,应该还没有真正生成代码,感兴趣的可以去了解一下JavaScript の変数と字句環境を段階的に理解します。ST语法树

看,以下代码:

 var val=111;
 function hahaha(){
     console.log(val);
 }
 function hihihi(){
    hahaha();
 }
 hihihi();  /// 111

的确是正确输出了,111

但是我更喜欢把 val放在一个函数中,如:

   function hahaha(){
       console.log(val);      /// (**)
   }
   function hihihi(){
      var val=111;            /// (*)
      hahaha();
   }
   hihihi();

结果就是Uncaught ReferenceError: val is not defined, 根本没找到val这个标识符,这是为什么?

因为执行过程是这样的:

  1. hihihi函数执行  , 然后为 val赋值……
  2. hahaha函数执行
  3. hahaha找不到val标识符,便去外部词法环境
  4. hahaha外部词法环境就是** hahaha函数声明时代码的外部**,即全局代码(下称全局词法环境)
  5. 全局词法环境没找到val,终了。
    (请注意3-5步, 找val找的是函数声明代码的外部,而不是函数调用时的位置。)

现在应该提一下概念了,词法环境(Lexical Environment)就是根据代码结构时决定的作用域,也可以称作词法作用域(Lexical Scoping)它是静态作用域。可以这么说,在源代码写好时,所有标识符的作用域就已经被决定。当然也有动态作用域,你可以去试试bash脚本,它就是动态的。嘿嘿。详细也可以参考静态作用域词法作用域

此处只要发现了个中区别就极好掌握,所以我就略了。

词法环境的抽象

在Javascript常用三种词法环境: 一、块级作用域 二、全局作用域 三、函数作用域。

有时,我们会将一个词法环境(即作用域,下面我会正式使用词法环境替代作用域这个术语)抽象成伪代码,如下:

	LexicalEnvironment = {
		OuterEnv:  ,
		This :    ,
		EnvironmentRecord:{
			// ... identifiername:variable
		}
	}

很简单:

  • OuterEnv:当前词法环境的外部词法环境
  • This: 当前词法环境的 this的值,但它是运行时决定的。
  • EnvironmentRecord(环境记录): 标识符-变量的映射,注意,这里的标识符只是单纯的字符串,变量指的是存储区的数据。而且标识符必须是当前词法环境,而不是当前代码的。

例如:

  function first(){
      var a  =100;
      let d = 220;
      {     // Block, 
          var b = a+100;
          let c = b*10;
          console.log(a,b,c,d);
      }
  }
  first();  // 100 200 2000 220

一定不要忽略first函数中的块级作用域,这很重要。

然后写成抽象就是:
函数内部的块级作用域

	BlockEnv = {
		OuterEnv:  ,
		This :    ,
		EnvironmentRecord:{
			c:              // 这里没有b
		}
	}

函数作用域

	FuncEnv = {
		OuterEnv:  ,
		This :    ,
		EnvRec:{
			a:,
			d:,
			b:
		}
	}

OKay,先到这里吧。

一些问题:

1、为什么用词法环境代替作用域
–词法环境涵盖了作用域,但反之则不能。
–但注意,词法作用域和词法作用域链与作用域以及作用域链都可通用。

2、环境记录是什么?
–当前环境下的标识符-变量的映射
–但是标识符只是“合法标识符”的字符串形式。
–变量是是指存储区的内容,但是确切说法是存储区

最后

我把我的笔记,重新整理后发到博客上后发现——我笔记干净了好多,艹。

核心を深く掘り下げるこの種のコンテンツは非常に便利であり、コードを記述する際の柔軟性も大幅に高まります。ここが最も役に立つ場所だと思います最後に:
私の個人的な理解では、私はよく間違いを犯すということですが、よく見るとどこを見ればよいのかわかりません。

この記事は、https://blog.csdn.net/krfwill/article/details/106155266から転載されています: https://blog.csdn.net/krfwill/article/details/106155266

関連チュートリアルの推奨事項:

JavaScript ビデオチュートリアル

以上がJavaScript の変数と字句環境を段階的に理解します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
前の記事:WEBプログラマー向けの