1. 函数声明 **fucntion f() {}** 会自动提升到作用域的最顶部,因此我们可以在函数定义语句之前书写函数调用语句 **f()**
    2. 如果同一个函数被多次声明,后面的声明就会覆盖前面的声明

    JavaScript 引擎将函数名视同变量名,所以采用function命令声明函数时,整个函数会像变量声明一样,被提升到代码头部。所以,下面的代码不会报错。

    1. f();
    2. function f() {}

    表面上,上面代码好像在声明之前就调用了函数f。但是实际上,由于“变量提升”,函数f被提升到了代码头部,也就是在调用之前已经声明了。但是,如果采用赋值语句定义函数,JavaScript 就会报错。

    1. f();
    2. var f = function (){};
    3. // TypeError: undefined is not a function

    上面的代码等同于下面的形式。

    1. var f;
    2. f();
    3. f = function () {};

    上面代码第二行,调用f的时候,f只是被声明了,还没有被赋值,等于undefined,所以会报错。

    注意,如果像下面例子那样,采用function命令和var赋值语句声明同一个函数,由于存在函数提升,最后会采用var赋值语句的定义。

    1. var f = function () {
    2. console.log('1');
    3. }
    4. function f() {
    5. console.log('2');
    6. }
    7. f() // 1

    上面例子中,表面上后面声明的函数f,应该覆盖前面的var赋值语句,但是由于存在函数提升,实际上正好反过来。

    如果同一个函数被多次声明,后面的声明就会覆盖前面的声明。

    1. function f() {
    2. console.log(1);
    3. }
    4. f() // 2
    5. function f() {
    6. console.log(2);
    7. }
    8. f() // 2

    上面代码中,后一次的函数声明覆盖了前面一次。而且,由于函数名的提升(参见下文),前一次声明在任何时候都是无效的,这一点要特别注意。

    1. <script>
    2. test(); // => Uncaught ReferenceError: test is not defined
    3. </script>
    4. <script>
    5. function test() {
    6. console.log('test');
    7. }
    8. </script>

    通过字面量声明的函数,会提升到 脚本块(script 元素) 的顶部。但是,并不会越过脚本块。