Hướng dẫn how to check javascript flow of execution - cách kiểm tra luồng thực thi javascript

Có một trang web trên đó một khóa đặc biệt được tạo dựa trên dữ liệu trên trang nguồn. Tôi có thể bằng cách nào đó "từng bước" xem quy trình thực thi mã JavaScript trên trang web này để tìm khóa khóa này được tạo ở đâu không? Tôi có nghĩa là với khả năng theo dõi tất cả các biến cục bộ / toàn cầu được tạo và thay đổi trong quá trình thực thi mã.

P.S. Khóa này không được lưu trữ ở bất cứ đâu, nó được tạo trong mã JavaScript, với khóa này có kết nối nền với ổ cắm web và sau đó khóa này không được sử dụng ở bất kỳ nơi nào khác.

Khi được hỏi ngày 25 tháng 5 năm 2020 lúc 18:49May 25, 2020 at 18:49

1

Tất cả mã JavaScript cần được lưu trữ và chạy trong một số loại môi trường. Trong hầu hết các trường hợp, môi trường đó sẽ là một trình duyệt web.

Đối với bất kỳ đoạn mã JavaScript nào được thực thi trong trình duyệt web, rất nhiều quy trình diễn ra phía sau hậu trường. Trong bài viết này, chúng ta sẽ xem xét mọi thứ xảy ra đằng sau hậu trường để mã JavaScript chạy trong trình duyệt web.

Trước khi chúng ta đi sâu, đây là một số điều kiện tiên quyết để làm quen với bản thân, bởi vì chúng ta sẽ sử dụng chúng thường xuyên trong bài viết này.

  • Trình phân tích cú pháp: Trình phân tích cú pháp hoặc trình phân tích cú pháp cú pháp là một chương trình đọc từng dòng mã của bạn. Nó hiểu cách mã phù hợp với cú pháp được xác định bởi ngôn ngữ lập trình và những gì nó [mã] dự kiến ​​sẽ làm.: A Parser or Syntax Parser is a program that reads your code line-by-line. It understands how the code fits the syntax defined by the Programming Language and what it [the code] is expected to do.
  • Công cụ JavaScript: Công cụ JavaScript chỉ đơn giản là một chương trình máy tính nhận mã nguồn JavaScript và biên dịch nó với hướng dẫn nhị phân [mã máy] mà CPU có thể hiểu. Các công cụ JavaScript thường được phát triển bởi các nhà cung cấp trình duyệt web và mỗi trình duyệt chính có một. Các ví dụ bao gồm động cơ V8 cho Google Chrome, Spidermonkey cho Firefox và Chakra cho Internet Explorer.: A JavaScript engine is simply a computer program that receives JavaScript source code and compiles it to the binary instructions [machine code] that a CPU can understand. JavaScript engines are typically developed by web browser vendors, and each major browser has one. Examples include the V8 engine for Google chrome, SpiderMonkey for Firefox, and Chakra for Internet Explorer.
  • Tuyên bố chức năng: Đây là các chức năng được gán một tên.: These are functions that are assigned a name.
function doSomething[] { //here "doSomething" is the function's name
statements; 
} 
  • Biểu thức chức năng: Đây là các hàm ẩn danh, đó là các hàm không có tên hàm như js function [] { statements }. Chúng thường được sử dụng trong các câu lệnh, như gán một hàm cho một biến. ________số 8.: These are anonymous functions, that is functions without a function name like js function [] { statements }. They are usually used in statements, like assigning a function to a variable. let someValue = function [] { statements }.

Bây giờ, rằng chúng tôi đã tránh xa những thứ đó, chúng ta hãy lao vào.

Cách mã JavaScript được thực thi

Vì những người không biết, trình duyệt không hiểu mã JavaScript cấp cao mà chúng tôi viết trong các ứng dụng của chúng tôi. Nó cần được chuyển đổi thành một định dạng mà trình duyệt và máy tính của chúng tôi có thể hiểu - mã máy.

Trong khi đọc qua HTML, nếu trình duyệt gặp mã JavaScript để chạy qua thẻ hoặc thuộc tính có chứa mã JavaScript như

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
0, nó sẽ gửi nó đến công cụ JavaScript của nó.

Sau đó, công cụ JavaScript của trình duyệt tạo ra một môi trường đặc biệt để xử lý việc chuyển đổi và thực hiện mã JavaScript này. Môi trường này được gọi là

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
1.
getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
1
.

Bối cảnh thực thi chứa mã hiện đang chạy và mọi thứ hỗ trợ thực thi.

Trong thời gian chạy ngữ cảnh thực thi, mã cụ thể được phân tích cú pháp, các biến và hàm được lưu trữ trong bộ nhớ, mã byte có thể thực thi được tạo và mã được thực thi.

Có hai loại bối cảnh thực thi trong JavaScript:

  • Bối cảnh thực thi toàn cầu [GEC]
  • Bối cảnh thực thi chức năng [FEC]

Hãy xem xét chi tiết cả hai.

Bối cảnh thực thi toàn cầu [GEC]

Bối cảnh thực thi chức năng [FEC]

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
2.

Hãy xem xét chi tiết cả hai.not inside of a function gets executed.

Bất cứ khi nào công cụ JavaScript nhận được một tệp tập lệnh, trước tiên nó sẽ tạo ra một bối cảnh thực thi mặc định được gọi là
getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
2.

Bối cảnh thực thi chức năng [FEC]

Hãy xem xét chi tiết cả hai.

Bất cứ khi nào công cụ JavaScript nhận được một tệp tập lệnh, trước tiên nó sẽ tạo ra một bối cảnh thực thi mặc định được gọi là

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
2.

GEC là bối cảnh thực thi cơ sở/mặc định trong đó tất cả mã JavaScript không nằm trong hàm được thực thi.

Đối với mỗi tệp JavaScript, chỉ có thể có một GEC.

Bất cứ khi nào một hàm được gọi, công cụ JavaScript sẽ tạo ra một loại bối cảnh thực thi khác được gọi là bối cảnh thực thi chức năng [FEC] trong GEC để đánh giá và thực thi mã trong hàm đó.

  1. Vì mọi cuộc gọi chức năng đều có FEC của riêng mình, nên có thể có nhiều hơn một FEC trong thời gian chạy của một tập lệnh.
  2. Bối cảnh thực thi được tạo ra như thế nào?

Vì mọi cuộc gọi chức năng đều có FEC của riêng mình, nên có thể có nhiều hơn một FEC trong thời gian chạy của một tập lệnh.

Bối cảnh thực thi được tạo ra như thế nào?

Bây giờ chúng ta nhận thức được bối cảnh thực thi là gì và các loại khác nhau có sẵn, chúng ta hãy xem xét cách tạo ra.

  1. Việc tạo ra một bối cảnh thực thi [GEC hoặc FEC] xảy ra theo hai giai đoạn:
  2. Giai đoạn sáng tạo
  3. Giai đoạn thực hiện

Trong giai đoạn sáng tạo, bối cảnh thực thi đầu tiên được liên kết với đối tượng bối cảnh thực thi [ECO]. Đối tượng bối cảnh thực thi lưu trữ rất nhiều dữ liệu quan trọng mà mã trong bối cảnh thực thi sử dụng trong thời gian chạy của nó.

Giai đoạn tạo xảy ra trong 3 giai đoạn, trong đó các thuộc tính của đối tượng bối cảnh thực thi được xác định và đặt. Các giai đoạn này là:

Tạo đối tượng biến [VO]

Tạo chuỗi phạm vi

Đặt giá trị của từ khóa

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
3

Hãy để chúng tôi đi qua từng giai đoạn chi tiết.

Giai đoạn tạo: Tạo đối tượng biến [VO]Hoisting. Since this is an important concept, we'll talk about it briefly before moving on to the next stage.

Đối tượng biến [VO] là một thùng chứa giống như đối tượng được tạo trong bối cảnh thực thi. Nó lưu trữ các biến và khai báo chức năng được xác định trong bối cảnh thực thi đó.

Trong GEC, đối với mỗi biến được khai báo với từ khóa

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
4, một thuộc tính được thêm vào VO chỉ vào biến đó và được đặt thành 'không xác định'.

Chức năng nâng cao

Trong hầu hết các kịch bản khi xây dựng một ứng dụng, các nhà phát triển có thể chọn xác định các chức năng ở đầu tập lệnh và chỉ sau đó gọi chúng xuống mã, như vậy:

Tuy nhiên, do nâng cao, điều ngược lại vẫn sẽ hoạt động. Trường hợp chúng ta có thể gọi các chức năng đầu tiên sau đó xác định chúng sau đó xuống tập lệnh.

Trong mã trên, khai báo hàm

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
5 sẽ được lưu trữ trong bộ nhớ của VO, làm cho nó có sẵn để sử dụng ngay cả trước khi nó được xác định.

Tăng cường biến

Các biến được khởi tạo với từ khóa

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
4 được lưu trữ trong bộ nhớ của Vo cảnh thực hiện hiện tại là một thuộc tính và được khởi tạo với giá trị
getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
7. Điều này có nghĩa là, không giống như các chức năng, cố gắng truy cập giá trị của biến trước khi nó được xác định sẽ dẫn đến
getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
7.

Quy tắc nâng cơ sở nâng

Tăng chỉ hoạt động cho các khai báo chức năng, không biểu thức. Dưới đây là một ví dụ về biểu thức chức năng trong đó thực thi mã sẽ bị phá vỡ.

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};

Việc thực thi mã bị phá vỡ, bởi vì với các biểu thức chức năng,

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
5 sẽ được nâng như một biến không phải là một hàm. Và với việc nâng biến biến, giá trị của nó sẽ được đặt thành
getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
7. Đó là lý do tại sao chúng tôi gặp lỗi:

Ngoài ra, việc nâng biến không hoạt động cho các biến được khởi tạo với từ khóa

var occupation = "Frontend Developer"; 

function addOne[x] { 
    console.log[x + 1] 
}
1 hoặc
var occupation = "Frontend Developer"; 

function addOne[x] { 
    console.log[x + 1] 
}
2. Cố gắng truy cập một biến trước khai báo và sử dụng các từ khóa
var occupation = "Frontend Developer"; 

function addOne[x] { 
    console.log[x + 1] 
}
1 và
var occupation = "Frontend Developer"; 

function addOne[x] { 
    console.log[x + 1] 
}
2 để khai báo sau này sẽ dẫn đến
var occupation = "Frontend Developer"; 

function addOne[x] { 
    console.log[x + 1] 
}
5.

Trong trường hợp này, chúng sẽ được nâng lên nhưng không được gán với giá trị mặc định là

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
7.
var occupation = "Frontend Developer"; 

function addOne[x] { 
    console.log[x + 1] 
}
7 sẽ ném lỗi:

Giai đoạn sáng tạo: Tạo chuỗi phạm vi

Sau khi tạo ra đối tượng biến [VO], việc tạo ra chuỗi phạm vi là giai đoạn tiếp theo trong giai đoạn sáng tạo của bối cảnh thực hiện.

Phạm vi trong JavaScript là một cơ chế xác định mức độ có thể truy cập của một đoạn mã với các phần khác của cơ sở mã. Phạm vi trả lời các câu hỏi: Từ đâu có thể truy cập một đoạn mã? Nó không thể truy cập từ đâu? Điều gì có thể truy cập nó, và những gì không thể?

Mỗi bối cảnh thực thi chức năng tạo phạm vi của nó: không gian/môi trường nơi các biến và hàm mà nó xác định có thể được truy cập thông qua một quy trình gọi là phạm vi.

Điều này có nghĩa là vị trí của một cái gì đó trong một cơ sở mã, nghĩa là, nơi có một đoạn mã.

Khi một hàm được xác định trong một hàm khác, hàm bên trong có quyền truy cập vào mã được xác định theo hàm bên ngoài và của cha mẹ. Hành vi này được gọi là phạm vi từ vựng.lexical scoping.

Tuy nhiên, hàm bên ngoài không có quyền truy cập vào mã trong hàm bên trong.

Khái niệm về phạm vi này mang đến một hiện tượng liên kết trong JavaScript gọi là đóng cửa. Đây là khi các hàm bên trong luôn có quyền truy cập vào mã được liên kết với các hàm bên ngoài, ngay cả sau khi thực hiện các hàm bên ngoài hoàn tất. Bạn có thể tìm hiểu thêm đóng cửa ở đây.

Hãy xem xét một số ví dụ để hiểu rõ hơn:

  • Bên phải là phạm vi toàn cầu. Đây là phạm vi mặc định được tạo khi tập lệnh
    var occupation = "Frontend Developer"; 
    
    function addOne[x] { 
        console.log[x + 1] 
    }
    8 được tải và có thể truy cập từ tất cả các chức năng trong suốt mã.
  • Hộp màu đỏ là phạm vi của hàm
    var occupation = "Frontend Developer"; 
    
    function addOne[x] { 
        console.log[x + 1] 
    }
    9, xác định biến
    window.occupation = "Frontend Developer"; 
    window.addOne = [x] => { 
    console.log[x + 1]
    };
    0 và hàm
    window.occupation = "Frontend Developer"; 
    window.addOne = [x] => { 
    console.log[x + 1]
    };
    1.
  • Trong màu xanh lá cây là phạm vi của hàm
    window.occupation = "Frontend Developer"; 
    window.addOne = [x] => { 
    console.log[x + 1]
    };
    1. Có một câu lệnh
    window.occupation = "Frontend Developer"; 
    window.addOne = [x] => { 
    console.log[x + 1]
    };
    3 là in các biến
    window.occupation = "Frontend Developer"; 
    window.addOne = [x] => { 
    console.log[x + 1]
    };
    4,
    window.occupation = "Frontend Developer"; 
    window.addOne = [x] => { 
    console.log[x + 1]
    };
    5 và
    window.occupation = "Frontend Developer"; 
    window.addOne = [x] => { 
    console.log[x + 1]
    };
    6.

Bây giờ các biến

window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
4 và
window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
5 không được xác định trong hàm
window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
1, chỉ
window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
6. Tuy nhiên, do phạm vi từ vựng, nó có quyền truy cập vào phạm vi của hàm mà nó nằm trong và của cha mẹ của nó.

Khi chạy mã, động cơ JS sẽ không tìm thấy biến

window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
5 trong phạm vi của hàm
window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
1. Vì vậy, nó nhìn lên phạm vi của cha mẹ, bắt đầu với chức năng ____29. Ở đó, nó tìm thấy biến
var msg = "I will rule the world!"; 

function printMsg[] { 
    console.log[this.msg]; 
} 

printMsg[]; // logs "I will rule the world!" to the console.
4. Nó quay trở lại hàm
window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
1 và giải quyết biến
window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
5 ở đó với nó.

Quá trình tương tự cho biến

window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
4. Động cơ JS nhìn lên qua phạm vi của tất cả cha mẹ của nó cho đến phạm vi của GEC, giải quyết giá trị của nó trong hàm
window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
1.

Ý tưởng này về động cơ JavaScript vượt qua phạm vi của bối cảnh thực thi mà một hàm được định nghĩa để giải quyết các biến và hàm được gọi trong chúng được gọi là chuỗi phạm vi.scope chain.

Chỉ khi công cụ JS không thể giải quyết một biến trong chuỗi phạm vi, nó mới ngừng thực thi và ném lỗi.

Tuy nhiên, điều này không hoạt động lạc hậu. Đó là, phạm vi toàn cầu sẽ không bao giờ có quyền truy cập vào các biến của hàm bên trong trừ khi chúng là

var msg = "I will rule the world!"; 

function printMsg[] { 
    console.log[this.msg]; 
} 

printMsg[]; // logs "I will rule the world!" to the console.
9 từ hàm.

Chuỗi phạm vi hoạt động như một kính một chiều. Bạn có thể nhìn thấy bên ngoài, nhưng mọi người từ bên ngoài không thể nhìn thấy bạn.

Và đó là lý do tại sao mũi tên màu đỏ trong hình trên là hướng lên trên bởi vì đó là hướng duy nhất mà chuỗi phạm vi đi.

Giai đoạn tạo: Đặt giá trị của từ khóa "này"

Giai đoạn tiếp theo và cuối cùng sau khi phạm vi trong giai đoạn tạo của bối cảnh thực thi đang đặt giá trị của từ khóa

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
3.

Từ khóa JavaScript

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
3 đề cập đến phạm vi nơi bối cảnh thực thi thuộc về.

Khi chuỗi phạm vi được tạo, giá trị của

var msg = "I will rule the world!"; 
const Victor = {
    msg: "Victor will rule the world!", 
    printMsg[] { console.log[this.msg] }, 
}; 

Victor.printMsg[]; // logs "Victor will rule the world!" to the console.
2 được khởi tạo bởi động cơ JS.

var msg = "I will rule the world!"; 
const Victor = {
    msg: "Victor will rule the world!", 
    printMsg[] { console.log[this.msg] }, 
}; 

Victor.printMsg[]; // logs "Victor will rule the world!" to the console.
3 trong bối cảnh toàn cầu

Trong GEC [bên ngoài bất kỳ chức năng và đối tượng nào],

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
3 đề cập đến đối tượng toàn cầu - đó là đối tượng
var msg = "I will rule the world!"; 
const Victor = {
    msg: "Victor will rule the world!", 
    printMsg[] { console.log[this.msg] }, 
}; 

Victor.printMsg[]; // logs "Victor will rule the world!" to the console.
5.

Do đó, các khai báo chức năng và các biến được khởi tạo với từ khóa

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
4 được gán dưới dạng thuộc tính và phương thức cho đối tượng toàn cầu - đối tượng
var msg = "I will rule the world!"; 
const Victor = {
    msg: "Victor will rule the world!", 
    printMsg[] { console.log[this.msg] }, 
}; 

Victor.printMsg[]; // logs "Victor will rule the world!" to the console.
5.

Điều này có nghĩa là việc khai báo các biến và chức năng bên ngoài bất kỳ chức năng nào, như thế này:

var occupation = "Frontend Developer"; 

function addOne[x] { 
    console.log[x + 1] 
}

Giống hệt như:

window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};

Các chức năng và biến trong GEC được đính kèm dưới dạng các phương thức và thuộc tính cho đối tượng cửa sổ. Đó là lý do tại sao đoạn trích bên dưới sẽ trả về đúng.

var msg = "I will rule the world!"; 
const Victor = {
    msg: "Victor will rule the world!", 
    printMsg[] { console.log[this.msg] }, 
}; 

Victor.printMsg[]; // logs "Victor will rule the world!" to the console.
3 trong các chức năng

Trong trường hợp của FEC, nó không tạo đối tượng

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
3. Thay vào đó, nó có quyền truy cập vào môi trường mà nó được xác định.

Đây sẽ là đối tượng

var msg = "I will rule the world!"; 
const Victor = {
    msg: "Victor will rule the world!", 
    printMsg[] { console.log[this.msg] }, 
}; 

Victor.printMsg[]; // logs "Victor will rule the world!" to the console.
5, vì hàm được xác định trong GEC:

var msg = "I will rule the world!"; 

function printMsg[] { 
    console.log[this.msg]; 
} 

printMsg[]; // logs "I will rule the world!" to the console.

Trong các đối tượng, từ khóa

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
3 không trỏ đến GEC, mà là chính đối tượng. Tham khảo
getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
3 trong một đối tượng sẽ giống như:

var name = "Victor";

function first[] {
  var a = "Hi!";
  second[];
  console.log[`${a} ${name}`];
}

function second[] {
  var b = "Hey!";
  third[];
  console.log[`${b} ${name}`];
}

function third[] {
  var c = "Hello!";
  console.log[`${c} ${name}`];
}

first[];
3

Xem xét ví dụ mã dưới đây:

var msg = "I will rule the world!"; 
const Victor = {
    msg: "Victor will rule the world!", 
    printMsg[] { console.log[this.msg] }, 
}; 

Victor.printMsg[]; // logs "Victor will rule the world!" to the console.

Mã nhật ký

var name = "Victor";

function first[] {
  var a = "Hi!";
  second[];
  console.log[`${a} ${name}`];
}

function second[] {
  var b = "Hey!";
  third[];
  console.log[`${b} ${name}`];
}

function third[] {
  var c = "Hello!";
  console.log[`${c} ${name}`];
}

first[];
4 vào bảng điều khiển chứ không phải
var name = "Victor";

function first[] {
  var a = "Hi!";
  second[];
  console.log[`${a} ${name}`];
}

function second[] {
  var b = "Hey!";
  third[];
  console.log[`${b} ${name}`];
}

function third[] {
  var c = "Hello!";
  console.log[`${c} ${name}`];
}

first[];
5 bởi vì trong trường hợp này, giá trị của từ khóa
getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
3, hàm có quyền truy cập là của đối tượng được xác định, không phải đối tượng toàn cầu.

Với giá trị của bộ từ khóa

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
3, tất cả các thuộc tính của đối tượng bối cảnh thực thi đã được xác định. Dẫn đến cuối giai đoạn sáng tạo, bây giờ động cơ JS chuyển sang giai đoạn thực hiện.

Giai đoạn thực thi

Cuối cùng, ngay sau giai đoạn sáng tạo của bối cảnh thực hiện xuất hiện trong giai đoạn thực thi. Đây là giai đoạn thực thi mã thực tế bắt đầu.

Cho đến thời điểm này, VO chứa các biến với các giá trị của

getAge[1990]; 
var getAge = function [yearOfBirth] {
console.log[new Date[].getFullYear - yearOfBirth] 
};
7. Nếu mã được chạy vào thời điểm này, nó bị ràng buộc trả về các lỗi, vì chúng ta không thể làm việc với các giá trị không xác định.

Ở giai đoạn này, công cụ JavaScript đọc mã trong bối cảnh thực thi hiện tại một lần nữa, sau đó cập nhật VO với các giá trị thực của các biến này. Sau đó, mã được phân tích cú pháp bởi trình phân tích cú pháp, được chuyển sang mã byte có thể thực thi và cuối cùng được thực thi.

Ngăn xếp thực thi, còn được gọi là ngăn xếp cuộc gọi, theo dõi tất cả các bối cảnh thực thi được tạo ra trong vòng đời của một tập lệnh.Call Stack, keeps track of all the Execution Contexts created during the life cycle of a script.

JavaScript là ngôn ngữ đơn luồng, điều đó có nghĩa là nó chỉ có khả năng thực hiện một nhiệm vụ tại một thời điểm. Do đó, khi các hành động, chức năng và sự kiện khác xảy ra, bối cảnh thực hiện được tạo cho mỗi sự kiện này. Do tính chất duy nhất của JavaScript, một loạt các bối cảnh thực thi chồng chất sẽ được thực thi được tạo ra, được gọi là

var name = "Victor";

function first[] {
  var a = "Hi!";
  second[];
  console.log[`${a} ${name}`];
}

function second[] {
  var b = "Hey!";
  third[];
  console.log[`${b} ${name}`];
}

function third[] {
  var c = "Hello!";
  console.log[`${c} ${name}`];
}

first[];
9.

Khi các tập lệnh tải trong trình duyệt, bối cảnh toàn cầu được tạo dưới dạng bối cảnh mặc định nơi công cụ JS bắt đầu thực thi mã và được đặt ở dưới cùng của ngăn xếp thực thi.

Động cơ JS sau đó tìm kiếm các cuộc gọi chức năng trong mã. Đối với mỗi cuộc gọi chức năng, một FEC mới được tạo cho chức năng đó và được đặt trên đầu bối cảnh thực thi hiện đang thực hiện.

Bối cảnh thực thi ở đầu ngăn xếp thực thi trở thành bối cảnh thực thi đang hoạt động và sẽ luôn được thực hiện trước tiên bởi động cơ JS.

Ngay khi việc thực thi tất cả các mã trong bối cảnh thực thi đang hoạt động được thực hiện, động cơ JS sẽ bật ra bối cảnh thực thi chức năng cụ thể đó của ngăn xếp thực thi, di chuyển về phía bên dưới nó, v.v.

Để hiểu quá trình làm việc của ngăn xếp thực thi, hãy xem xét ví dụ mã bên dưới:

var name = "Victor";

function first[] {
  var a = "Hi!";
  second[];
  console.log[`${a} ${name}`];
}

function second[] {
  var b = "Hey!";
  third[];
  console.log[`${b} ${name}`];
}

function third[] {
  var c = "Hello!";
  console.log[`${c} ${name}`];
}

first[];

Đầu tiên, tập lệnh được tải vào động cơ JS.

Sau đó, động cơ JS tạo ra GEC và đặt nó vào cơ sở của ngăn xếp thực hiện.

Biến js function [] { statements }0 được xác định bên ngoài bất kỳ chức năng nào, vì vậy nó nằm trong GEC và được lưu trữ trong nó là VO.

Quá trình tương tự xảy ra đối với các hàm

var occupation = "Frontend Developer"; 

function addOne[x] { 
    console.log[x + 1] 
}
9,
window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
1 và js function [] { statements }3.

Đừng nhầm lẫn về lý do tại sao chúng hoạt động vẫn còn trong GEC. Hãy nhớ rằng, GEC chỉ dành cho mã JavaScript [biến và hàm] không nằm trong bất kỳ chức năng nào. Bởi vì chúng không được xác định trong bất kỳ chức năng nào, các khai báo chức năng nằm trong GEC. Có ý nghĩa bây giờ 😃?not inside of any function. Because they were not defined within any function, the function declarations are in the GEC. Make sense now 😃?

Khi động cơ JS bắt gặp cuộc gọi chức năng

var occupation = "Frontend Developer"; 

function addOne[x] { 
    console.log[x + 1] 
}
9, một FEC mới được tạo cho nó. Bối cảnh mới này được đặt trên đỉnh của bối cảnh hiện tại, hình thành cái gọi là
var name = "Victor";

function first[] {
  var a = "Hi!";
  second[];
  console.log[`${a} ${name}`];
}

function second[] {
  var b = "Hey!";
  third[];
  console.log[`${b} ${name}`];
}

function third[] {
  var c = "Hello!";
  console.log[`${c} ${name}`];
}

first[];
9.

Trong suốt thời gian của cuộc gọi chức năng

var occupation = "Frontend Developer"; 

function addOne[x] { 
    console.log[x + 1] 
}
9, bối cảnh thực thi của nó trở thành bối cảnh hoạt động trong đó mã JavaScript được thực thi lần đầu tiên.

Trong hàm

var occupation = "Frontend Developer"; 

function addOne[x] { 
    console.log[x + 1] 
}
9, biến js function [] { statements }8 được lưu trữ trong FEC của nó, không phải trong GEC.

Tiếp theo, hàm

window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
1 được gọi trong hàm
var occupation = "Frontend Developer"; 

function addOne[x] { 
    console.log[x + 1] 
}
9.

Việc thực hiện hàm

var occupation = "Frontend Developer"; 

function addOne[x] { 
    console.log[x + 1] 
}
9 sẽ được tạm dừng do tính chất đơn của JavaScript. Nó phải đợi cho đến khi thực hiện nó, đó là hàm
window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
1, đã hoàn tất.

Một lần nữa, động cơ JS thiết lập một FEC mới cho chức năng

window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
1 và đặt nó ở đầu ngăn xếp, làm cho nó trở thành bối cảnh hoạt động.

Hàm

window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
1 trở thành bối cảnh hoạt động, biến let someValue = function [] { statements }5 được lưu trữ trong FEC của nó và hàm js function [] { statements }3 được gọi trong hàm
window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
1. FEC của nó được tạo ra và đặt trên đầu của ngăn xếp thực thi.

Bên trong hàm js function [] { statements }3, biến let someValue = function [] { statements }9 được lưu trữ trong FEC của nó và thông báo 0 được đăng nhập vào bảng điều khiển.

Do đó, chức năng đã thực hiện tất cả các nhiệm vụ của nó và chúng tôi nói nó 1. FEC của nó bị xóa khỏi đỉnh của ngăn xếp và FEC của hàm

window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
1 gọi là hàm js function [] { statements }3 trở lại là bối cảnh hoạt động.

Quay trở lại chức năng

window.occupation = "Frontend Developer"; 
window.addOne = [x] => { 
console.log[x + 1]
};
1, thông báo 5 được đăng nhập vào bảng điều khiển. Hàm hoàn thành nhiệm vụ của mình, 1 và bối cảnh thực thi của nó bị bật ra khỏi ngăn xếp cuộc gọi.

Khi hàm đầu tiên được thực thi hoàn toàn, ngăn xếp thực thi của hàm đầu tiên xuất hiện từ ngăn xếp. Do đó, điều khiển quay trở lại GEC của mã.

Và cuối cùng, khi việc thực thi toàn bộ mã được hoàn thành, động cơ JS sẽ loại bỏ GEC khỏi ngăn xếp hiện tại.

Bối cảnh thực thi toàn cầu Vs. Bối cảnh thực thi chức năng trong JavaScript

Vì bạn đã đọc tất cả các cách cho đến phần này, hãy tóm tắt các điểm chính giữa GEC và FEC với bảng bên dưới.

Bối cảnh thực thi toàn cầuChức năng thực thi bối cảnh
Tạo một đối tượng biến toàn cầu lưu trữ các khai báo chức năng và biến.Không tạo ra một đối tượng biến toàn cầu. Thay vào đó, nó tạo ra một đối tượng đối số lưu trữ tất cả các đối số được truyền cho hàm.
Tạo đối tượng `` này lưu trữ tất cả các biến và hàm trong phạm vi toàn cầu là phương thức và thuộc tính.Không tạo đối tượng `này, nhưng có quyền truy cập vào môi trường mà nó được xác định. Thông thường đối tượng `window`.
Không thể truy cập mã của bối cảnh hàm được xác định trong đóDo phạm vi, có quyền truy cập vào mã [các biến và hàm] trong bối cảnh nó được xác định và của cha mẹ của nó
Đặt không gian bộ nhớ cho các biến và hàm được xác định trên toàn cầuĐặt không gian bộ nhớ chỉ cho các biến và hàm được xác định trong hàm.

Sự kết luận

Bối cảnh thực thi của JavaScript là cơ sở để hiểu chính xác nhiều khái niệm cơ bản khác.

Bối cảnh thực thi [GEC và FEC] và ngăn xếp cuộc gọi là các quy trình được thực hiện dưới mui xe bởi công cụ JS cho phép mã của chúng tôi chạy.

Hy vọng bây giờ bạn có một sự hiểu biết tốt hơn trong đó đặt hàng các chức năng/mã của bạn chạy và cách động cơ JavaScript đối xử với chúng.

Là một nhà phát triển, có một sự hiểu biết tốt về các khái niệm này giúp bạn:

  • Nhận được một sự hiểu biết tốt về các ngôn ngữ trong và ngoài của ngôn ngữ.
  • Nhận được một nắm bắt tốt về một ngôn ngữ các khái niệm cơ bản/cốt lõi.
  • Viết mã sạch, có thể bảo trì và có cấu trúc tốt, đưa ít lỗi hơn vào sản xuất.

Tất cả điều này sẽ làm cho bạn một nhà phát triển tốt hơn nói chung.

Hy vọng bạn tìm thấy bài viết này hữu ích. Hãy chia sẻ nó với bạn bè và mạng của bạn, và vui lòng kết nối với tôi trên Twitter và blog của tôi, nơi tôi chia sẻ một loạt các bài viết và tài nguyên giáo dục miễn phí. Điều này thực sự thúc đẩy tôi xuất bản nhiều hơn.

Cảm ơn bạn đã đọc, và mã hóa hạnh phúc!

Học mã miễn phí. Chương trình giảng dạy nguồn mở của Freecodecamp đã giúp hơn 40.000 người có được việc làm với tư cách là nhà phát triển. Bắt đầu

JavaScript được thực thi theo thứ tự nào?

JavaScript là đồng bộ.Điều này có nghĩa là nó sẽ thực thi khối mã của bạn theo đơn đặt hàng sau khi nâng.Trước khi mã thực thi, các tuyên bố của VAR và chức năng được nâng lên trên đỉnh của phạm vi của chúng.after hoisting. Before the code executes, var and function declarations are “hoisted” to the top of their scope.

Làm thế nào mã JavaScript được thực thi?

Trong giai đoạn thực thi mã, JavaScript là một ngôn ngữ luồng duy nhất chạy qua dòng mã theo từng dòng và cập nhật các giá trị của hàm và biến được lưu trữ trong giai đoạn phân bổ bộ nhớ trong thành phần bộ nhớ.

JavaScript có thực thi từng dòng không?

JavaScript là ngôn ngữ đơn luồng, trong đó chỉ có một lệnh thực thi tại một thời điểm.Nó có một mô hình thực thi đồng bộ, trong đó mỗi dòng được thực hiện theo từng dòng, từ trên xuống dưới.each line is executed line by line, top to bottom.

Là JavaScript luôn được thực hiện tuần tự?

Theo mặc định, JavaScript chạy trong một quy trình duy nhất - trong cả trình duyệt web và nút.JS.Cái gọi là vòng lặp sự kiện tuần tự thực hiện các tác vụ [các đoạn mã] bên trong quá trình đó. – in both web browsers and Node. js. The so-called event loop sequentially executes tasks [pieces of code] inside that process.

Bài Viết Liên Quan

Chủ Đề