JavaScript 簡寫語法 1、簡寫的閉包自執行函數(Immediately Invoked Function Expression (IIFE)) 使用括弧將函數定義包裹起來,再在末尾加上另一對括弧,即可創建一個自執行函數。例如: (() => { console.log("Hello, wo ...
變數提升與函數提升
變數聲明提升
- 通過var定義(聲明)的變數--在定義語句之前就可以訪問到
- 值為undefined
console.log(a); //undefined
var a = 1;
//執行順序
var a;
console.log(a);
a = 1;
函數聲明提升
- 通過function聲明的函數--在之前就可以直接調用
- 值為函數定義(對象)
fn();//可調用
function fn(){
conse.log('哈哈');
}
執行上下文
代碼分類--位置
全局代碼
函數(局部)代碼
全局執行上下文
-
在執行全局代碼前將window確定為全局執行上下文
- 對全局數據進行預處理
- var定義的全局變數-->undefined--添加為window的屬性
- function聲明的全局函數-->賦值--添加為window的方法
- this-->賦值window
- 開始執行全局代碼
//全局執行上下文 console.log(a1, window.a1); //undefined undefined a2(); //a2(); console.log(this); //window var a1 = 3; function a2() { console.log('a2()'); } console.log(a1);
函數執行上下文
-
在調用函數--準備執行函數體之前--創建對應的函數執行上下文對象--虛擬的,存在於棧中
- 對局部數據進行預處理
- 形參變數-->賦值(實參)--添加為執行上下文的屬性
- arguments-->賦值(實參列表)--添加為執行上下文的屬性
- var定義的局部變數-->underfined--添加為執行上下文的屬性
- this-->賦值(調用函數的對象)
- 開始執行函數體代碼
//函數執行上下文 function fn(a1) { console.log(a1); //2 console.log(a2); //undefined a3(); //a3 console.log(this); //window console.log(arguments); //2,3 var a2 = 4; function a3() { console.log('a3'); } } fn(2, 3);
執行上下文棧
- 在全局代碼執行前--JS引擎會創建一個棧來存儲管理所有的執行上下文對象
- 在全局執行上下文(window)確定後--將其添加到棧中(壓棧)
- 在函數執行上下文創建後--將其添加到棧中(壓棧)
- 在當前函數執行完後--將棧頂的對象移除(出棧)
- 當所有代碼執行完成後--棧中只剩下window
<script>
//執行全局上下文
var a = 10;
var bar = function (x) {
var b = 5;
foo(x + b); //進入foo執行上下文
}
var foo = function (y) {
var c = 5;
console.log(a + c + y);
}
bar(10); //進入bar函數執行上下文
</script>
面試題
console.log('gb:' + i);
var i = 1;
foo(1);
function foo(i) {
if (i == 4) {
return;
};
console.log('fb:' + i);
foo(i + 1);
console.log('fe:' + i);
}
console.log('ge:' + i);
function a(){};
var a;
console.log(a); //f a(){}--變數先被提升--函數覆蓋變數後提升
if(!(b in window)){
var b = 1;
}
console.log(b); //undefined--變數先被提升為全局變數
var c = 1;
function c(c){
var c = 3;
}
c(2); //報錯--變數先被提升--函數後被提升--變數最後被賦值--因此不是函數,不能被調用