1. 程式人生 > >js作用域鏈和預編譯

js作用域鏈和預編譯


 js引擎執行分為兩步,預解析 程式碼執行

(1)預解析: js引擎會拿js裡面所有的var還有 function 提升到當前作用域的最前面
(2)程式碼執行:按照程式碼書寫的順序從上往下執行


預解析分為:變數預解析(變數提升)和函式預解析(函式提升)
變數提升就是把所有的變數宣告提升到作用域的最前面,不提升賦值操做
函式提升:就是把所有函式提升到作用域的最前面,不呼叫函式

作用域鏈:內部函式訪問外部函式的變數時,採取的是鏈式查詢的方式來決定取哪個值,一層(大括號)一層往外找

 

下面有幾個小題目,大家先嚐試著思考並且得出答案,有疑問的話可以看問題後面註釋部分的解析。每次在瀏覽器控制檯測試一個題目時,記得註釋其他題目哦,否則會相互影響。

解題思路:先預解析,再根據作用域鏈查詢


1 <script> 2 3 //問題1 變數預解析(變數提升)第一種情況 4 console.log(num1); 5 var num1 = 10; 6 //結果undefined 7 8 9 /* 相當於執行了以下程式碼 10 var num1; 11 console.log(num1); 12 num1 = 10; */ 13 14 15 16 17 // 問題2 變數預解析(變數提升)第二種情況 18 fun1(); 19 var fun1 = function() { 20 console.log("這裡測試變數預解析"); 21 } 22 /* 相當於執行了以下程式碼 23 var fun1; 24 fun1(); 25 fun1 = function() { 26 console.log("這裡測試變數預解析"); 27 } */ 28 29 30 // 問題3 31 fun2(); 32 33 function fun2() { 34 console.log("函式預解析"); 35 } 36 37 /* 相當於執行了以下程式碼 38 function fun2() { 39 console.log("函式預解析"); 40 } 41 fun2(); */ 42 43 44 // 預解析案例1 45 var num = 10; 46 fun3(); 47 48 function fun3() { 49 console.log("fun3" + num); 50 var num = 20; 51 } 52 53 /* 相當於執行了以下程式碼 54 var num; 55 56 function fun3() { 57 var num; 58 console.log(num); //先變數提升,然後根據作用域鏈查詢 59 num = 20; 60 61 } 62 num = 10; 63 fun3(); */ 64 65 66 // 案例2 67 var num4 = 10; 68 69 function fun4() { 70 console.log("fun4" + num4); 71 var num4 = 20; 72 console.log("fun4" + num4); 73 } 74 fun4(); 75 76 /* 相當於執行了以下程式碼 77 var num4; 78 79 function fun4() { 80 var num4; 81 console.log(num4); 82 num4 = 20; 83 console.log(num4); 84 } 85 num4 = 10; 86 fun4(); */ 87 88 89 90 // 案例3 91 var a = 18; 92 fun5(); 93 94 function fun5() { 95 var b = 9; 96 console.log(a); 97 console.log(b); 98 var a = '123'; 99 } 100 101 102 /* 相當於執行了以下程式碼 103 var a; 104 function fun5() { 105 var b; 106 var a; 107 b = 9; 108 console.log(a); 109 console.log(b); 110 a = '123'; 111 } 112 a = 18; 113 fun5(); */ 114 115 116 // 案例4 117 fun6(); 118 console.log("fun6 " + p); 119 console.log("fun6 " + n); 120 console.log("fun6 " + m); 121 122 function fun6() { 123 var a = b = c = 9; 124 console.log("fun6 " + m); 125 console.log("fun6 " + n); 126 console.log("fun6 " + p); 127 } 128 129 130 /* 131 相當於執行了以下程式碼 132 133 function fun6() { 134 // 注: var m = n = p = 9; 相當於 var m = 9; n = 9; p = 9; 所以n p 直接賦值,是全域性變數 135 136 // 而 var m = 9, n = 9, p = 9; 相當於 var m = 9; var n = 9; var p = 9; 137 var m; 138 m = 9; 139 n = 9; 140 p = 9; 141 142 console.log(m); 143 console.log(n); 144 console.log(p); 145 } 146 fun6(); 147 console.log(p); 148 console.log(n); 149 console.log(m); */ 150 </script>

&n