2012-02-21 43 views
40

Tiêu đề của tôi khá nhiều tổng cộng.'Thực thi ngữ cảnh' trong JavaScript chính xác là gì?

bất cứ ai có thể soi sáng cho tôi về ...

"là gì 'Execution Context' trong JavaScript?"

và cách nó liên quan đến 'điều này', cẩu, chuỗi nguyên mẫu, phạm vi và thu gom rác thải?

+1

Bạn có thể cần xác định ** Ngữ cảnh thực thi ** – jondavidjohn

+5

@jondavidjohn: * Ngữ cảnh thực thi * có ý nghĩa cụ thể trong [ECMA-262] (http://bclary.com/2004/11/07/#a- 10). – josh3736

+0

@ josh3736 cảm ơn! – jondavidjohn

Trả lời

40

Bạn đang hỏi về khái niệm khác nhau mà không liên quan rất chặt chẽ. Tôi sẽ cố gắng giải quyết một cách ngắn gọn.


Thực hiện bối cảnh là một khái niệm trong spec ngôn ngữ mà — trong điều khoản của layman — khoảng tương đương với các 'môi trường' một chức năng thực hiện trong; có nghĩa là, phạm vi biến (và chuỗi phạm vi , các biến trong bao đóng từ phạm vi bên ngoài), đối số chức năng và giá trị của đối tượng this.

Ngăn xếp cuộc gọi là tập hợp các ngữ cảnh thực thi.

Xem thêm this answerthis article.


Phạm vi là nghĩa đen rằng: phạm vi trong đó một biến thể được truy cập. Đơn giản:

var x; 

function a() { 
    var y; 
} 

x có thể được truy cập từ mọi nơi. Khi a được gọi, x sẽ nằm trong phạm vi bên ngoài. (Lưu trữ trong chuỗi phạm vi.)

Ngược lại, y chỉ có thể được truy cập bằng mã trong a() bởi vì nó được giới hạn trong phạm vi a 's. Đây là những gì từ khóa var thực hiện: hạn chế một biến cho phạm vi cục bộ. Nếu chúng tôi bỏ qua var, y sẽ kết thúc trong phạm vi toàn cầu toàn cầu, thường được coi là điều xấu.


Hãy suy nghĩ về cẩu như nhiều hơn một điều thời gian biên dịch. Trong JavaScript, chức năng khai báo được "treo" lên đầu phạm vi của chúng. Nói cách khác, chúng được phân tích cú pháp và đánh giá trước bất kỳ mã nào khác. (Điều này trái với hàm biểu thức, được đánh giá nội dòng.) Hãy xem xét những điều sau đây:

a(); 
b(); 

function a() { } 
var b = function() { } 

Cuộc gọi đến a() sẽ thành công vì tuyên bố của nó được nâng lên đỉnh; a được gán tự động trước khi bắt đầu thực hiện chương trình. Các cuộc gọi đến b() sẽ thất bại với một TypeErrorb sẽ không được xác định cho đến khi dòng 4.

+15

Trên thực tế, liên quan đến bit của bạn trên cẩu, khai báo biến 'b' cũng sẽ được hoisted: nó sẽ được khai báo ngay từ đầu, nhưng không có giá trị nào được gán cho nó trước dòng 4. Gọi' b() 'trước dòng 4 thực sự sẽ dẫn đến một lỗi, nhưng một lỗi khác: chúng tôi sẽ cố thực thi 'undefined', không phải là một hàm. – Pioul

+0

@ josh3736 Tôi thực sự thích câu trả lời của bạn, nhưng tôi không hiểu là nguyên nhân gây ra ngăn xếp để chuyển đổi ngữ cảnh như trong một hàm không đồng bộ hoặc một vòng lặp trong khi nó dường như không? –

-2

Tôi cho rằng một ví dụ đơn giản sẽ giải thích mọi thứ.

Lưu ý: function.call(object) cuộc gọi chức năng function trong bối cảnh object

// HTML 

​<p id="p"></p>​​​​​​​​​​​​​​​​​​​​​​​​ 

// JavaScript 

function helloWorld() { 
    alert("HelloWorld: " + this); 
} 

var p = document.getElementById("p"); 
helloWorld();    // HelloWorld: [object DOMWindow] 
helloWorld.call(window);  // HelloWorld: [object DOMWindow] 
​​​​​​helloWorld.call("String"); // HelloWorld: String // Note: "toString()" 
helloWorld.call​​​​(p);   // HelloWorld: [object HTMLParagraphElement] 
helloWorld.call(new Date());​​​​ // HelloWorld: Tue Feb 21 2012 21:45:17 GMT+0100 (Central Europe Standard Time) 
+5

Câu trả lời này khá rõ ràng ....... – Pacerier

+0

Câu trả lời này khá thông tin. call() là thuộc tính của prototype nguyên mẫu. Nó có thể được gọi trên bất kỳ chức năng nào.Vì helloWorld() về cơ bản thực hiện một var_dump() của thuộc tính này của đối tượng được truyền, bạn sẽ được thông báo giá trị của giá trị này cho bất kỳ giá trị nào bạn chuyển vào. ... và đó là điều đôi khi khó về javascript. Thật dễ dàng để mất vị trí của bạn trong chuỗi phạm vi. – shotdsherrif

+1

OP hỏi về 'bối cảnh thực thi' không phải là 'bối cảnh'. 'Ngữ cảnh thực thi' có một định nghĩa rất cụ thể trong thông số ECMAScript bao gồm 'Môi trường Lexical', 'tham chiếu Môi trường' bên ngoài, 'Bản ghi môi trường', ngăn xếp, điều khiển chương trình và thuộc tính [[Scope]] bên trong. – user2312341

-3

Thực hiện Bối cảnh là một wrapper để giúp quản lý các mã đang chạy Trong mã của bạn, bạn sẽ thấy rất nhiều của môi trường từ vựng có nghĩa là lĩnh vực mã giữa {} nhưng cái nào hiện đang chạy được quản lý thông qua ngữ cảnh thực thi.nó có thể chứa mã của bạn và nó cũng có thể chứa đựng những gì bạn đã viết trong mã của mình.

2

Tôi đã giải quyết chỉ các chủ đề có liên quan chặt chẽ nhất.

Ngữ cảnh thực thi là trình bao bọc xung quanh mã hiện tại của bạn; chứa mã số mà bạn chưa viết; nhưng được tạo bởi Động cơ JS .

Nó bao gồm những điều sau đây -

  1. Global Object
  2. 'này'
  3. môi trường Outer
  4. đang bạn

Một Exec ution Context được tạo mỗi khi bạn chạy tệp .js/app của bạn. Bước đầu tiên trong giai đoạn tạo này là Hoisting. Không gian dự trữ JS Engine không gian hoặc thiết lập bộ nhớ cho tất cả các biến và chức năng được xác định trong của bạn. Sau đó, chúng sẽ được truy cập khi mã của bạn được thực thi theo từng dòng.

Ví dụ:

b(); 
console.log(a); 
var a = "hi!"; 
function b() { 
    console.log("calling function"); 
} 

Ở đây, chức năng b()biến một đều truy cập trước khi chúng được xác định, tuy nhiên, do cẩu giao diện điều khiển sẽ không ném bất kỳ lỗi .

Kết quả sẽ như thế nào - (thử nó)

calling function 
undefined 

Thông báo bao hàm được thực hiện hoàn toàn, nhưng chúng ta không xác định cho biến. Điều này là do Hoisting được thực hiện khác nhau cho các hàm so với các biến. Chức năng như một toàn thể được chọn vào bộ nhớ, nhưng đối với các biến, không gian được dành riêng như một giữ chỗ với giá trị là undefined. Giá trị thực tế sau đó được thay thế khi công cụ thực thi mã dòng của bạn.

Tôi hy vọng điều này sẽ làm rõ khái niệm cho bạn.

1

Bạn đã hỏi rất nhiều khái niệm nhưng hãy chọn từng khái niệm một theo cách & hiểu chúng.

Môi trường mà mã của bạn đang chạy là Execution context. Nó được tạo khi mã của bạn được thực hiện.

Execution Context (Global), được tạo ra bởi JS cơ chứa 3 điều quan trọng đối với bạn:

  1. toàn cầu đối tượng - window
  2. đặc biệt Object this
  3. Ref với môi trường bên ngoài

Cho phép xem một cách đơn giản ví dụ để hiểu Global Execution Context:

var a = "Hello World"; 

function b(){ 

} 

Khi JS Engine chạy mã trên này nó tạo ra sau bối cảnh Execution (hiển thị trong hình ảnh): Global Execution Context


Bây giờ chúng ta hãy xem làm thế nào JS Engine sẽ tạo Execution Context (sau đó chúng tôi sẽ đào ra & hiểu cẩu) : xem xét kịch bản này:

b(); 
console.log(a); 

var a = "Hello World!"; 
function b(){ 
    console.log("Called b!"); 
} 

tôi có thể gọi hàm b() mặc dù nó là d eclared sau đó. Điều này có nghĩa JS Engine đang làm điều gì đó trước khi mã của tôi được thực thi, cho phép xem những gì:

JS động cơ thực hiện sau hai bước để trong khi thực hiện bất kỳ mã:

TẠO GIAI ĐOẠN:

  • JS Phân tích cú pháp động cơ - chạy qua mã của bạn & identifies variables & functions được tạo theo mã (sẽ được sử dụng trong giai đoạn thực hiện)
  • Thiết lập không gian bộ nhớ cho Biến & Chức năng - "Treo"
  • Treo - trước khi mã của bạn được thực thi, Engine JS thiết lập không gian bộ nhớ asides cho Var & Func sử dụng bên trong mã. Các biến này & chức năng bao gồm bối cảnh thực thi của bất kỳ chức năng nào được thực thi. Tất cả các biến trong JS ban đầu được đặt thành không xác định.

Thực hiện GIAI ĐOẠN: khá đơn giản để hiểu,

  • Khi mã được thực thi line-by-line (bởi JS interpreeter) nó có thể truy cập các biến định nghĩa bên Execution Context
  • chuyển nhượng biến được thực hiện trong giai đoạn này

Một công cụ thực thi mới ntext được tạo ra bất cứ khi nào chức năng gọi là có

Execution Context Stack: gì xảy ra khi bạn gọi một hàm:

function b(){ 

} 

function a(){ 
    b(); 
} 

a(); 
  • Bây giờ trước hết Global Execution Context sẽ được tạo (như đã giải thích ở trên)

  • sau đó thực hiện bắt đầu và giao tiếp er encounters call to function a()here a new execution context is created pushed on top EC Stack

    vì vậy bất cứ khi nào bạn gọi hàm EC mới được tạo & được đặt ở trên cùng của ngăn xếp EC.

  • vì vậy bây giờ EC for a()CREATED interpreeter sẽ thực thi mã bên a() line-by-line

  • sau đó intrepreeter gặp call to function b(), điều này tạo khác EC mà được đẩy lên trên hoặc EC chồng

  • Khi b() kết thúc, nó sẽ được bật lên ngăn xếp sau đó a() sẽ kết thúc & tất cả các con đường xuống Global EC

see Execution Stack for above code snippet

+0

Để biết thêm thông tin, hãy xem tại đây http://davidshariff.com/blog/what-is-the-execution-context-in-javascript/ –

0

Các "Thực hiện ngữ cảnh" là một chiếc ô mà kết thúc tốt đẹp tất cả các mã để giúp quản lý nó. Nó giống như một người quản lý quản lý bất kỳ môi trường nào. Vì có quá nhiều môi trường từ vựng vì trong một ứng dụng JavaScript, bạn có rất nhiều biến và hàm bạn cần một cách để quản lý mọi thứ. Cái gì đến trước, cái gì đến thứ hai và vân vân, và nếu bạn không có môi trường "Thực thi bối cảnh" thì mọi thứ đều đi vào địa ngục. Vì vậy, hãy xem xét "Execution Context" một trình bao bọc, một người quản lý quản lý mã của bạn.

Các vấn đề liên quan