2015-07-10 17 views
5

Tôi không thực sự là một javascript noob ở tất cả, mặc dù trong toàn bộ cuộc sống của tôi tôi đã không bao giờ đi qua này, nhưng tôi phải trong giả định rằng javascript phải gán chức năng trước khi chạy bất cứ điều gì hay cái gì?Các hàm được xác định bất kể thứ tự?

Trong tất cả kinh nghiệm của tôi, tôi mong đợi điều này sẽ trả về 'không xác định', nhưng rõ ràng là nó trả về 'hàm'.

function bar() { 
    return foo; 
    foo = 10; 
    function foo() {} 
    var foo = '11'; 
} 
alert(typeof bar()); 

Có ai đó có thể giải thích điều này cho tôi không?

+0

bản sao có thể có của [Chức năng và phạm vi chức năng Javascript] (http://stackoverflow.com/questions/7506844/javascript-function-scoping-and-hoisting) – DTing

+0

Có. Khi nhập [* ngữ cảnh thực thi *] (http://ecma-international.org/ecma-262/6.0/index.html#sec-execution-contexts), tất cả các khai báo hàm và biến được xử lý trước khi bất kỳ mã nào được chạy. – RobG

Trả lời

7

Hành vi này của JavaScript được gọi là cẩu. Có một lời giải thích tốt về MDN (https://developer.mozilla.org/en-US/docs/Glossary/Hoisting)

Trong JavaScript, chức năng và biến được hoisted. Hoisting là hành vi của JavaScript về việc chuyển các khai báo đến đỉnh của một phạm vi (phạm vi toàn cục hoặc phạm vi chức năng hiện tại).

Điều đó có nghĩa là bạn có thể sử dụng hàm hoặc biến trước khi nó được khai báo hoặc nói cách khác: một hàm hoặc biến có thể được khai báo sau khi đã được sử dụng.

Về cơ bản, nếu bạn khai báo một biến như thế này:

console.log(s);    // s === undefined 
var s = 'some string'; 

s khai sẽ được "treo" đến đầu phạm vi (ví dụ: sẽ không có ReferenceError trên phù hợp với console.log). Giá trị của biến số sẽ không được xác định tại thời điểm đó mặc dù.

Cũng vậy với giao một chức năng ẩn danh cho một biến, vì vậy:

console.log(f);    // f === undefined 
f();      // TypeError: f is not a function 
var f = function() {};  // assigning an anonymous function as a value 
f();      // ok, now it is a function ;) 

Biến sẽ được kéo lên và do đó có thể nhìn thấy trong toàn bộ phạm vi, nhưng giá trị của nó, ngay cả khi đó là một chức năng, sẽ vẫn chưa được xác định - do đó sẽ xảy ra lỗi nếu bạn cố thực thi nó.

Mặt khác nếu bạn khai báo một tên chức năng:

console.log(f);    // f === function f() 
f();      // we can already run it 
function f() {};   // named function declaration 

nét Nó cũng sẽ được kéo lên, do đó bạn có thể chạy nó ngay cả trong dòng đầu tiên của phạm vi bạn đã tuyên bố nó.

+0

Tôi thực sự không thích thuật ngữ "cẩu", nó là một từ sai, và giải thích tham chiếu là người nghèo. Nó cho rằng mã được di chuyển bằng cách nào đó, nó không phải là. Câu trả lời thực sự là các khai báo hàm và biến được * xử lý * trước khi bất kỳ mã nào được thực hiện. – RobG

+0

Giải thích rõ ràng, cảm ơn bạn rất nhiều điều này rõ ràng này, tôi thậm chí không biết rằng javascript đã làm điều này với các chức năng lồng nhau, tôi nghĩ rằng nó chỉ là phạm vi gốc .. Silly tôi –

+0

@RobG Yeah, điểm công bằng. Nó hơi giống với những gì chúng tôi đã có với "chức năng tự gọi" trong một thời gian, phải không? Tôi cũng không phải là một fan hâm mộ (bạn nên nghe nó được dịch sang ngôn ngữ của tôi như thế nào, nó giống như "độ cao")). Đó là một thuật ngữ được chấp nhận và tôi nghĩ sẽ dễ giải thích hơn khi không đi sâu vào chi tiết nếu hy sinh tính chính xác một chút) –

0

Cũng trong chức năng JavaScript là gì ngoài Object.

Khi bạn nói thanh typeof(), trong hàm thanh bạn đang trở foo mà là một function.You chỉ trở về tên của hàm, Vì vậy, nó trả lại constructor của foo function.So, của bạn typeof nhận giá trị của foo constructor là loại hàm. Do đó, nó cảnh báo chức năng.Nó vẫn tham khảo các fooclosure

Một lần nữa trong thanh, định nghĩa, bạn trở về foo, nhưng định nghĩa của nó vẫn chưa encountered.In JavaScript khi trong khi phân tích các hướng dẫn, tuyên bố biến và chức năng được đặt trên đầu trong phạm vi chức năng hiện tại.

Vì vậy, tuyên bố của bạn

function bar() { 
    return foo; 
    foo = 10; 
    function foo() {} 
    var foo = '11'; 
} 

tương đương với

function bar() { 
    function foo() {} 
    return foo; 
    foo = 10; 

    var foo = '11'; 

này được gọi là JavaScript top hoist

} 
0

này được khá dễ dàng kiểm tra;

foo(1); 

function foo(i) { 
    if (bar()) { 
     alert("foo called, bar true, i = " + i); 
    }; 
} 

foo(2); 

function bar() { 
    return true; 
} 

foo(3); 

DEMO

Điều này cho thấy rằng Javascript tải tất cả các chức năng trước khi thực hiện bất cứ điều gì. Không có vấn đề gì chức năng đặt hàng được xác định.

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