上一章:JS的數據類型 傳送門:https://segmentfault.com/a/11...javascript
好!話很少少,咱們就開始吧。對變量提高和函數聲明的理解,能讓你更清楚容易的理解,爲何你的程序報錯了~哈哈哈css
咱們前端的代碼通常就三個部分組成html + css +js,通常呢咱們的JS又會放在最後執行。html
執行上下文:
所謂的執行上下文,就是JS代碼執行的環境。前端
Javascript中代碼的運行環境分爲如下三種:java
全局上下文 - 這個是默認的代碼運行環境,一旦代碼被載入,引擎最早進入的就是這個環境。segmentfault
函數上下文 - 當執行一個函數時,運行函數體中的代碼。閉包
Eval上下文 - 在Eval函數內運行的代碼。函數
這個和做用域有點像。
每次調用一個函數將會建立一個新的執行上下文會,被添加到做用域鏈的頂部。
做用域和執行上下文之間最大的區別是: 執行上下文在運行時肯定,隨時可能改變;做用域在定義時肯定,永遠不會改變。學習
其實上面那些看看就好,直接看代碼吧。this
JS代碼在執行以前會先全局中變量提高、函數聲明。在函數中變量提高、函數聲明(this、函數參數也會提高,函數中的變量提高的範圍是這個函數的內部)
變量提高:變量賦值的過程:聲明---初始化---賦值
舉例子:函數內部的變量提高(全局的變量提高也是同理)
function fn(){ console.log(x);//undefined var x = 1; console.log(x);//1 } fn();
這裏咱們從針對變量x來解說:
1.在執行fn時,爲fn建立一個執行環境。(fn函數的執行上下文,也就是在fn這個函數範圍內)
2.找到fn函數執行上下文中(fn函數範圍內),全部用var聲明的變量。
3.將這些變量初始化爲undefined。
4.開始執行代碼。
5.把1賦值給變量x。
至關於以下這樣:
function fn(){ //把用var聲明的變量,提高到頂部,並初始化爲undefined var x =undefined; //開始執行代碼。 console.log(x);//undefined //把1賦值給變量x。 var x = 1; console.log(x);//1 } fn();
函數聲明:
cat();//123 function cat(){ console.log(123); } cat();//123
1.找到全部用function聲明的變量,並在環境中建立這些變量。
2.將這些變量初始化並賦值爲function(){xxx}
3.在環境中從上往下開始執行代碼。
至關於以下這樣:
//1.找到全部用function聲明的變量,並在環境中建立這些變量。 //2.將這些變量初始化並賦值爲function(){xxx} var cat = function (){ console.log(123); } //3.在環境中從上往下開始執行代碼。 cat();//123 cat();//123
這個就是函數聲明,在代碼執行前,會把function提到頂部。因此若是不行代碼,代碼塊裏即便有錯誤也不會報出來,只有執行時纔會運行代碼內部東西。
看到這裏應該有個初步瞭解了,那麼來看看下面的。加點難度,加深瞭解。
<!DOCTYPE html> <html> <head> <title>3543541</title> </head> <body> <script type="text/javascript"> fn2();//undefined fn();//undefined function fn(){ console.log(g); } fn();//undefined console.log(g);//undefined var g = 'global'; console.log(g);//global fn2()//global function fn2(){ console.log(g); } fn2()//global fn();//global </script> </body> </html>
爲何fn中的globle拿不到呢?而fn2的globle能拿到值呢?
運用上面學習的知識來分析一波。
上面代碼在執行前,會通過變量提高、函數聲明,因此在準備執行前的代碼是這樣的:
//函數聲明會在最最頂端 var fn = function (){ console.log(g); } var fn2 = function (){ console.log(g); } //執行函數和變量按照相對位置排列 //執行的相對位置不能變,這3個是在變量g以前執行的就要一直在g以前執行 fn2(); fn(); fn(); var g = undefined; console.log(g);//undefined var g = 'global'; console.log(g);//global //執行的相對位置不能變,這3個是在變量g以後執行的就要一直在g以後執行 fn2(); fn2(); fn();
這裏咱們能夠總結出一點規律:
1.函數聲明會在最最頂端
2.變量提高,只是在本身的範圍內提高
3.執行的相對位置不能變和變量按照執行上下文以前的相對位置排列。
4.函數執行時,按照執行位置查找變量做用域只會向上查找。
下一回:變量做用域與閉包