Why can I use a function before it's defined i

2018-12-31 18:35发布

This code always works, even in different browsers:

function fooCheck() {
  alert(internalFoo()); // We are using internalFoo() here...

  return internalFoo(); // And here, even though it has not been defined...

  function internalFoo() { return true; } //...until here!
}

fooCheck();

I could not find a single reference to why it should work, though. I first saw this in John Resig's presentation note, but it was only mentioned. There's no explanation there or anywhere for that matter.

Could someone please enlighten me?

7条回答
梦醉为红颜
2楼-- · 2018-12-31 19:12

It is called HOISTING - Invoke(called) a function before where it has been defined.

Two different types of functions that I want to write about are:

Expression Functions & Deceleration Functions

  1. Expression Functions:

    A function expression can be stored in a variable so they do not need function names. They will also named as an anonymous function (a function without a name).

    To invoke (called) they are always need using a variable name. These kind of functions won't work if calls before where it has been defined which means Hoisting is not happening here. We always must define the expression function first and then invoke it.

    let lastName = function (family) {
     console.log("My last name is " + family);
    };
    let x = lastName("Lopez");
    

    This is how you can write in ECMAScript 6:

    lastName = (family) => console.log("My last name is " + family);
    
    x = lastName("Lopez");
    
  2. Deceleration Functions:

    Functions are declared with the following syntax are not executed immediately. They are "saved for later use" and will be executed later, when they are invoked (called upon). These type of functions work if you call them BEFORE or AFTER where they have been defined. If you call a deceleration function before where it has been defined - Hoisting - works properly.

    function Name(name) {
      console.log("My cat's name is " + name);
    }
    Name("Chloe");
    

    Hoisting example:

    Name("Chloe");
    function Name(name) {
       console.log("My cat's name is " + name);
    }
    
查看更多
春风洒进眼中
3楼-- · 2018-12-31 19:23

I have only used JavaScript a little. I am not sure if this will help, but it looks very similar to what you are talking about and may give some insight:

http://www.dustindiaz.com/javascript-function-declaration-ambiguity/

查看更多
孤独总比滥情好
4楼-- · 2018-12-31 19:25

The browser reads your HTML from beginning to end and can execute it as it is read and parsed into executable chunks (variable declarations, function definitions, etc.) But at any point can only use what's been defined in the script before that point.

This is different from other programming contexts that process (compile) all your source code, perhaps link it together with any libraries you need to resolve references, and construct an executable module, at which point execution begins.

Your code can refer to named objects (variables, other functions, etc.) that are defined further along, but you can't execute referring code until all the pieces are available.

As you become familiar with JavaScript, you will become intimately aware of your need to write things in the proper sequence.

Revision: To confirm the accepted answer (above), use Firebug to step though the script section of a web page. You'll see it skip from function to function, visiting only the first line, before it actually executes any code.

查看更多
无色无味的生活
5楼-- · 2018-12-31 19:25

Some languages have the requirement that identifiers have to be defined before use. A reason for this is that the compiler uses a single pass on the sourcecode.

But if there are multiple passes (or some checks are postponed) you can perfectly live without that requirement. In this case, the code is probably first read (and interpreted) and then the links are set.

查看更多
有味是清欢
6楼-- · 2018-12-31 19:25

For the same reason the following will always put foo in the global namespace:

if (test condition) {
    var foo;
}
查看更多
ら面具成の殇う
7楼-- · 2018-12-31 19:27

The body of the function "internalFoo" needs to go somewhere at parsing time, so when the code is read (a.k.a parsing) by the JS interpreter, the data structure for the function is created and the name is assigned.

Only later, then the code is run, JavaScript actually tries to find out if "internalFoo" exists and what it is and whether it can be called, etc.

查看更多
登录 后发表回答