Rumah >hujung hadapan web >tutorial js >Menyahmistikan Timbunan Panggilan JavaScript: Cara Kod Anda Benar-Benar Berjalan

Menyahmistikan Timbunan Panggilan JavaScript: Cara Kod Anda Benar-Benar Berjalan

WBOY
WBOYasal
2024-08-21 06:07:361028semak imbas

Demystifying the JavaScript Call Stack: How Your Code Really Runs

Cara Timbunan panggilan JavaScript berfungsi ialah sesuatu yang ditanya oleh setiap pembangun bahagian hadapan sekurang-kurangnya sekali dalam kerjayanya, dan pada pendapat saya, ia bukan soalan yang telah telah dijawab di kebanyakan tempat, dan jawapannya tidak selalunya jelas atau mudah difahami. Itulah sebabnya saya telah memutuskan untuk membincangkan topik dalam siaran ini.

Mari kita mulakan dari awal. Enjin JavaScript menjalankan baris kod demi baris secara serentak, dan setiap kali fungsi dilaksanakan, ia mewujudkan konteks pelaksanaan (ruang dalam ingatan untuk menyimpan semua sifat berskop yang wujud sahaja di dalam fungsi itu) dan menambah fungsi pada timbunan panggilan.

JavaScript hanya melaksanakan kod fungsi yang berada di atas tindanan dan apabila fungsi memuktamadkan dan mengembalikan nilainya, enjin mengalih keluar fungsi daripada tindanan panggilan dan mula mengerjakan yang seterusnya.

Apabila timbunan panggilan kosong, enjin JavaScript terus menjalankan kod dalam konteks global seterusnya, atau perkara yang sama, terus melaksanakan baris yang berada dalam akar fail JavaScript dan tidak tergolong dalam mana-mana fungsi.

Mari kita lihat beberapa contoh, baris demi baris:

const num1 = 2;
const num2 = 5;

function sum(a, b){
return a + b;
}

const result= sum(num1, num2);
console.log(result) // 7

Ini ialah kod yang sangat mudah yang mentakrifkan 2 pemalar (num1 dan num2) dan kemudian mentakrifkan fungsi sum yang menjumlahkan 2 nombor dan mengembalikan hasil jumlah. Akhir sekali, pemalar hasil dicipta dan hasil pelaksanaan jumlah dengan argumen num1 dan num2 ditugaskan kepadanya. Kemudian nilai hasil dicetak pada konsol.

Jika anda berpendapat bahawa penjelasan sebelum ini terlalu mudah atau terlalu rumit dan tidak menjelaskan apa-apa, sila bersabar dengan saya, kita akan sampai ke perkara yang menarik.

Mari kita lihat apa yang dilakukan oleh enjin JavaScript, baris demi baris. Dalam baris pertama, enjin mencipta label num1 dan menyimpan dalam ingatan nilai 2.

const num1 = 2;

Barisan kedua melakukan perkara yang sama untuk label num2. Ia mencipta label num2 dan menyimpan dalam memori nilai 5.

const num2 = 5;

Ini bermakna apabila seseorang di dalam skop global memerlukan nilai num2 enjin akan menukar label dan meletakkan nilai 5 sebaliknya.

Mari kita teruskan dengan baris seterusnya. Baris seterusnya ialah fungsi jumlah. Apa yang anda fikir enjin akan lakukan? Adakah anda fikir ia akan melaksanakan fungsi atau menambahnya pada timbunan panggilan? Tidak! Apa yang enjin akan lakukan ialah simpan label baharu bernama jumlah dan simpan kod di dalam kurungan dalam ingatan. Atau apa yang sama, Ia akan menyimpan definisi fungsi dan menetapkannya pada label jumlah.

function sum(a, b){
return a + b;
}

jika kita dapat melihat secara visual memori kod yang telah kita jalankan setakat ini, kita akan melihat sesuatu seperti ini:

Label name Value in memory
num1 2
num2 5
sum function definition

Barisan seterusnya adalah sangat yang menarik. Apabila enjin JavaScript mencapai baris seterusnya, ia mencipta label hasil, tetapi pada ketika ini, ia belum tahu nilai apa yang perlu diberikan kepada label kerana nilai ialah hasil daripada melaksanakan fungsi, jadi pertama sekali, ia perlu melaksanakan fungsi itu, melakukan apa sahaja fungsi yang perlu dilakukan dan dapatkan hasil daripada nilai pulangan.

const result= sum(num1, num2);

Pada ketika ini, enjin menambah fungsi pada timbunan panggilan dan juga mencipta konteks pelaksanaan baharu, iaitu ruang dalam ingatan baharu adalah JavaScript boleh menyimpan nilai args dan setiap sifat lain yang berada di dalam fungsi tanpa bertembung dengan konteks global.

Call stack
sum
Global

First of all, the engine creates in memory the labels a and b which are the names given to the parameters, and it assigns the value of the arguments 2 and 5 respectively.

If we could see the memory at this specific moment, we would see something like this:

Label name Value in memory
a 2
b 5
return 2 + 5 = 7

In this case, the function is really simple and only returns the value of the sum between a and b, so the engine substitutes the parameters with the values of the arguments and returns the value to the global execution context. Finally, the function is removed from the call stack, and only the global context remains.

Call stack
Global

At this point, the result of the function is assigned to the label result and we can print the value on console with the console log.

Let's take a look at how the global memory looks now:

Label name Value in memory
num1 2
num2 5
sum function definition
result 7

Did you noticed? the label result has a value of 7? and also sum still has the function definition inside.

Let's take a look at the next code:

const num1 = 2;
const num2 = 5;

function sum(a, b){
return a + b;
}

const result= sum(num1, num2);
console.log(result) // 7

function sumThreeNumbers = (x,y,z) => {
return sum(x, y) + z
}

const result2 = sumThreeNumbers(4,6,2)
console.log(result2) // 12

The main difference is that now we have a new sumThreeNumbers function and we are creating a new result2 constant and assigning the value of running the function sumThreeNumbers with the arguments, 4, 6 and 2.

Let's take a look at how the call stack works when we run nested functions.

If we jump to the line when we define the constant result2 the global memory would look something like this:

Label name Value in memory
num1 2
num2 5
sum function definition
result 7
sumThreeNumbers function definition

Just as on the previous example, the JavaScript engine doesn't know what value to assign to the label result2, to get the value, first needs to execute the function sumThreeNumbers with the arguments. The function is added to the call stack, and a new execution context is created. The execution context would look like this:

Label name Value in memory
x 4
y 6
z 2

So the first thing that JavaScript does is create the parameter labels and assign the value provided by the arguments.

Now let's take a look at our call stack

Call stack
sumThreeNumbers
Global

As you can see, the call stack only has the sumThreeNumbers item (apart from the global context that is always present).

To be able to get the result value, the function sum needs to be executed first, so the engine will add the function to the call stack and create a new execution context for the sum function.

Call stack
sum
sumThreeNumbers
Global

As the sum function is on top of the call stack, Javascript needs to run sum first to be able to continue running sumThreeNumbers.

This is how it's going to look the execution context for the function sum:

Label name Value in memory
a 4
b 6
return 4 + 6 = 10

Seperti yang anda tahu, ia akan kembali _10 _dan ia akan dialih keluar daripada timbunan panggilan

Call stack
sumThreeNumbers
Global

JavaScript akan terus melaksanakan sumThreeNumbers dan konteks pelaksanaan akan kelihatan seperti ini:

Label name Value in memory
x 4
y 6
z 2
return 10 + 2 = 12

Ia akan mengembalikan nilai 12 dan dialih keluar daripada timbunan panggilan.

Call stack
Global

Kemudian nilai 12 akan diberikan kepada harta hasil2 dan nilai 12 akan dipaparkan dalam konsol.

Saya harap siaran ini dapat membantu anda memahami cara tindanan panggilan JavaScript berfungsi, jika ya sila tinggalkan komen dan suka. Saya jumpa anda dalam yang seterusnya!

Atas ialah kandungan terperinci Menyahmistikan Timbunan Panggilan JavaScript: Cara Kod Anda Benar-Benar Berjalan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn