国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

javascript作用域鏈與執行環境詳解

2019-11-19 17:02:06
字體:
來源:轉載
供稿:網友

前言:這是筆者學習之后自己的理解與整理。如果有錯誤或者疑問的地方,請大家指正,我會持續更新!

作用域、作用域鏈、執行環境、執行環境棧以及this的概念在javascript中非常重要,本人經常弄混淆,這里梳理一下;

  • 局部作用域函數內部的區域,全局作用域就是window;
  • 作用域鏈取決于函數被聲明時的位置,解析標識符的時候就先找當前作用域,再向外查找,直到全局,這樣一個順序;和函數在哪里調用無關;
  • 執行環境就是函數可訪問的數據和變量的集合,也就是函數的作用域鏈上的所有數據和變量;
  • 執行環境棧就是根據代碼執行順序,各執行環境按照棧的形式逐層訪問,并且用完了退出來扔掉;如果當前執行環境(存放當前作用域鏈里的數據和變量)找不到變量,那就是找不到了,不會往之前的那個執行環境查找,它和作用域鏈是不同的;
  • this是一個對象,它取決于是誰執行的,誰執行那就是誰;(this的概念還是不太清楚,這里寫的有點萬金油,過兩天再來修正) 

作用域

  JavaScript沒有塊級作用域的概念,只有函數級作用域:變量在聲明它們的函數體及其子函數內是可見的。

  作用域就是變量和函數的可訪問范圍,控制著變量和函數的可見性與生命周期,在JavaScript中變量的作用域有全局作用域和局部作用域。

變量沒有在函數內聲明或者聲明的時候沒有帶var就是全局變量,擁有全局作用域;

 <script type="text/javascript"> function test1(){  a = 1;//全局變量,只有在當前函數運行時,才有效  } test1(); console.log(a);//1 注意test1函數必須運行,不然找不到a </script>

全局變量可以當做window對象的屬性用,他們是一樣的; 

<script type="text/javascript">  var b = 1;//全局變量 console.log(b === window.b);//true 全局變量可以當做window對象的屬性用,他們是一樣的;</script>

window對象的所有屬性擁有全局作用域,在代碼任何地方都可以訪問;

函數內部聲明的變量就是局部變量,只能在函數體內使用,函數的參數雖然沒有使用var但仍然是局部變量。

 <script type="text/javascript">    var c = 1;//全局變量//   console.log(d);//ReferenceError: d is not defined 引用錯誤,當前作用域就是最外層作用域,依然找不到d   function test2(d){    console.log(c);//1 全局變量,哪都可以訪問;(先找當前作用域,找不到,就向外層作用域找,直到window最外層,找到了)    console.log(d);//3 形參是局部變量,只有當前作用域下可以訪問   }   test2(3);  </script>

作用域鏈

  作用域鏈取決于函數被聲明時的位置,解析標識符的時候就先從當前作用域開始找,在當前作用域中無法找到時,引擎就會在外層嵌套的作用域中繼續查找,直到找到該變量,或抵達最外層的作用域(也就是全局作用域)為止;它的路線已經被定死了,和函數在哪里運行無關;

<script type="text/javascript">   var a = 1;   var b = 2;   var c = 3;   var d = 4;   function inner(d) {//它的作用域鏈是inner---全局    var c = 8;    console.log(a);//1 當前作用域找不到a,去全局作用域找到了a=1    console.log(b);//2 當前作用域找不到b,去全局作用域找到了b=2    console.log(c);//8 當前作用域找到了c=8    console.log(d);//7 當前作用域找到了d=7,形參也是局部作用域   // console.log(e);//ReferenceError: e is not defined 引用錯誤,找不到e, 它的作用域鏈是inner---全局    console.log(a+b+c+d);//18   }   function outter(e) {    var a = 5;//inner()的作用域鏈是inner---全局,所以這個a相當于無效    var b = 6;//inner()的作用域鏈是inner---全局,所以這個a相當于無效    inner(7);   }   outter(999);//這個999無效,里面的e根本找不到</script>

在多層的嵌套作用域中可以定義同名的標識符,這叫作“遮蔽效應”,內部的標識符“遮蔽”了外部的標識符

通過window.a這種技術可以訪問那些被同名變量所遮蔽的全局變量。但非全局的變量如果被遮蔽了,無論如何都無法被訪問到;

<script type="text/javascript">   var a = 'Lily';   var b = 'Lucy';   function outer() {    var b = 'Jesica';    var c = 'Susan';    function inner(c) {     console.log(a);//Lily      console.log(window.b);//Lucy     console.log(b);//Jesica     console.log(c);//Jenifer    }    inner('Jenifer');   }   outer();</script>

執行環境

  執行環境(execution context),也叫執行上下文。每個執行環境都有一個變量對象(variable object),保存函數可訪問的所有變量和數據(也就是函數的作用域鏈上的所有數據和變量)。我們的代碼訪問不到它,它是給引擎使用的;

  執行環境棧,當執行進入一個函數時,函數的執行環境就會被推入一個棧中。而在函數執行完之后,棧將其執行環境移除,它里面的變量和數據會被標記清除,等待垃圾回收,再把控制權返回給之前的執行環境。javascript程序中的執行正是由這個機制控制著;

  需要注意的是如果當前執行環境(存放當前作用域鏈里的數據和變量)找不到變量,那就是找不到了,不會往之前的那個執行環境查找,和作用域鏈是不一樣的;

  代碼的執行順序也不全是一行一行的執行,而是和函數的調用順序有關:

  • 代碼進入全局執行環境,全局執行環境放入環境棧;
  • 當執行到一個函數時,就把這個函數的執行環境推入到環境棧頂端,之前的執行環境往后;
  • 全局執行環境最先進入,所以一直在底端;就和棧的概念差不多;
  • 函數執行完之后,再把它的執行環境從作用域鏈頂端移除,它保存的數據和函數都被標記清除,等待垃圾回收;
  • 控制權交給之前的執行環境,繼續往下執行;
  • 當頁面關閉時,全局執行環境才銷毀;
<script type="text/javascript"> var a = 1; var b = 2; var c = 3; var d = 4; function inner(d) {//它的作用域鏈是inner---全局  var c = 8;  console.log(a);//1 當前作用域找不到a,去全局作用域找到了a=1  console.log(b);//2 當前作用域找不到b,去全局作用域找到了b=2  console.log(c);//8 當前作用域找到了c=8  console.log(d);//7 當前作用域找到了d=7,形參也是局部作用域 // console.log(e);//ReferenceError: e is not defined 引用錯誤,找不到e, 它的作用域鏈是inner---全局  console.log(a+b+c+d);//18 } function outter(e) {  var a = 5;//inner()的作用域鏈是inner---全局,所以這個a相當于無效  var b = 6;//inner()的作用域鏈是inner---全局,所以這個a相當于無效  inner(7); } outter(999);//這個999無效,里面的e根本找不到</script>

以上代碼的執行順序:

代碼執行進入全局執行環境,并對全局執行環境中的代碼進入聲明提升;    
執行第2行,賦值a=1; 然后第3行賦值b=2; 然后第4行賦值c=3; 然后第5行賦值d=4;
執行第20行,調用outer(999)函數,然后進入outer(999)函數執行環境,聲明提升,并將實參999傳給形參e;現在環境棧中有兩個執行環境,outer(999)是當前執行環境;
執行第16行,賦值a=5; 然后第17行賦值b=6;    
執行第18行,調用inner(7)函數,然后進入inner(7)函數執行環境,聲明提升,并將實參7傳給形參d;
執行第7行,賦值c=8; 然后運算并輸出; 

代碼優化

  由于在作用域鏈上查找變量是需要消耗性能的,我們應該盡快的找到變量,所以在函數多層嵌套的時候,我們應盡可能的使用函數內部的局部變量;

  我們在函數內部使用全局變量可以說是一種跨作用域操作,如果某個跨作用域的值在函數的內部被多次使用,那么我們就把它存儲到局部變量里,這樣可以提高性能。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 万荣县| 肃南| 南宫市| 得荣县| 奉新县| 永寿县| 石泉县| 叶城县| 门源| 南宫市| 巍山| 桑日县| 芮城县| 高唐县| 赤壁市| 宁安市| 黄梅县| 收藏| 贺兰县| 靖安县| 集安市| 太保市| 丰顺县| 淳安县| 聂拉木县| 武定县| 丰城市| 通辽市| 尉犁县| 宜黄县| 漳州市| 咸宁市| 麻城市| 都兰县| 宕昌县| 靖西县| 桦甸市| 泊头市| 天等县| 奎屯市| 普陀区|