很早之前寫過棧和堆的結構,非常簡單的介紹了一下,主要是為了明白深拷貝和淺拷貝。最近突然發現了呼叫棧這個概念,理解這個概念對於一些函式的執行能更清晰的理解,比如遞迴。
棧(stack)是計算機中特殊的一個資料列表,棧有一個特點就是先進後出。我們可以把棧當做乒乓球的盒子,先放進去的最後才拿出來。今天只說說入棧和出棧兩個概念:
程式碼執行過程中會有呼叫棧(call stack)的概念,就是解析的機制,棧的一種執行結構。棧一定遵循先進後出。
有時候會讓自己鑽進牛角尖,比如棧是先進後出,那麼程式碼從上往下執行的時候,上面的程式碼先入棧,那麼為什麼上面的輸出會先執行?還有資料都是儲存在棧裡面,為什麼隨便可以取值?等等等等。
這些都是待研究的,這邊自己給了自己一個應該不正確的理解,棧有鏈式呼叫,就跟物件一樣,所以資料可以隨便呼叫。JavaScript執行上下文是按順序呼叫的,只有呼叫棧也叫作執行上下文棧才是先進後出。而執行上下文在JavaScript中跟作用域一樣,一個函式就是一個作用域,就是一個執行上下文。
看下面程式碼:
console.log('globals' + i);
var i = 1;
fn(1);
function fn(i) {
if(i == 4){
console.log('fns:'+ i);
return
}
console.log('fns:' + i);
fn(i + 1);
console.log('fne' + i);}
console.log('globale' + i);
複製程式碼
執行結果是:
globalsundefined
fns:1
fns:2
fns:3
fns:4
fne3
fne2
fne1
globale1
複製程式碼
程式碼執行的時候先生成一個window上下文執行棧,然後壓入棧中,接著執行到fn(1),把fn(1)壓入棧,fn(1)上下文執行,然後執行到fn(2),把fn(2)壓入棧,一直到fn(4),執行上下文棧裡面是這樣的:
Window上下文按順序執行,輸出globalsundefined,fn(1)上下文按順序執行先輸出fns:1,然後就把fn(2)壓入棧了,所以就輸出fns2,依次一直到fn(4)。這就是入棧的過程。然後開始出棧的執行,棧頂的先執行,當fn(4)執行完畢,就把fn(4)彈出棧,fn(3)就變成棧頂,fn(3)接著往下執行,輸出fne3,然後fn(3)彈出,依次一直到window。這就是出棧的過程。
執行上下文按順序執行,執行上下文棧(也叫呼叫棧)嚴格按照先進後出的順序執行。
按照正常的順序思維去理解或許更快更清晰得到答案,只是這些東西對於想要做些什麼的還是有必要去了解的。
解釋的不是很好,自己是明白了點,但是文字表述的不清楚,還有一些原理我自己也解釋不清,歡迎指教也歡迎留言。
Coding 個人筆記