zoukankan      html  css  js  c++  java
  • Javascript进阶(9)---函数声明与函数表达式的区别

    刚开始接触JavaScript,感觉它是个弱类型的脚本语言,语法十分宽松,好学好上手。

    过了一阵了,渐渐地感觉到这个脚本语言其实他并不“脚本”,也一点不弱”

    要是你不了解他的“弱”,不了解这种脚本语言的任性后果肯定是一次次的---“咦?明明没有错啊?这xx也行?”

    JavaScript中的函数声明函数表达式就是一个这样的例子,这两个平时我们看起来和使用起来没有什么差别的东西。

     两者区别的表现

    • JavaScript进阶(6)里面,介绍了几种“创建”函数的方法,其中头两种便是函数声明函数表达式
      //函数声明
      function funName(a, b) {
          //function body
      }
      //函数表达式,他最大的特点就是像给变量赋值,只不过赋的是一个匿名的函数对象
      var funName = function (a , b){
          //function body
      };
    • 在平时使用实际编程中,我们经常会把这两种方式混用,看起来没什么区别,让我们调用一下试试看                                                           

      • 函数声明                                                                                                                                                                     
      • 函数表达式:
        • 用函数声明创建的函数compareAB可以在compareAB定义之前就进行调用
        • 用函数表达式创建的compareAB函数不能在compareAB被赋值之前进行调用
        • 到这这两种区别的原因是javascript的解释器的变量提升Javascript hoisting)。

    变量提升

    In javascript, every variable declaration is hoisted to the top of its declaration context.

    JavaScript解释器,会将函数的声明、变量的声明提前到作用域(上下文)的最顶部先执行,但是变量初始化(赋值)的顺序不变

    • 上例子第一种情况在JavaScript解释器中是这样进行的                                                                                                                                    使用 function 的函数声明被提前到了最顶部先执行
    • 上例子第二种情况在JavaScript解释器中是这样进行的                                                                                                       这样看来就很容易理解了,在函数“创建”之前调用了它必然会报错
    • 其他的例子
      1 var myvar = 'outterValue';
      2 (function () {
      3   console.log(myvar);  
      4   var myvar = 'innerValue';
      5 }) ();

      变量提升后

      1 var myvar = 'outterValue';
      2 (function () {
      3   var myvar;            //未进行初始化,则值为undefined
      4   console.log(myvar);   //输出undefined
      5   myvar = 'innerValue';
      6 }) ();
    • 另一个深刻理解的例子
       1 var fun1;
       2 console.log(typeof (fun2)); //=>function    
       3 console.log(typeof (anonymous)); //=>undefined
       4 if (true) {
       5   function fun2() {
       6     console.log('我是if里面的fun2 ');
       7   }
       8   fun1 = function anonymous() {
       9     console.log('我是if里面的 fun1');
      10   }
      11 } else {
      12   function fun2() {
      13     console.log('我是else里面的fun2');
      14   }
      15   fun1 = function anonymous() {
      16     console.log('我是else里面的 fun1');
      17   }
      18 }
      19 fun2();  //我是else里面的fun2  
      20 fun1(); // 我是if里面的 fun1

      从中我们可以总结几点

      • if-else语句不会形成新的作用域,变量的提升提升到了全文的顶部
      • 检测到作用域内有两个同名的fun2函数的定义,第一个定义先被提升,第二个定义接着被提升(第二个定义在第一个定义之下),第二个定义覆盖了第一个fun2定义,所以fun2()是按照后者输出"我是else里面的fun2"
      • 而fun1是用函数表达式创建的,其表达式的内容是在JS运行时(不是解析时)才能确定(这里条件判断就起到作用了),所以fun1表达式执行了第一个函数定义并赋值,则fun1()输出"我是if里面的 fun1"
      • 相信大家不难把js解释器里面的真实执行过程写出来
         1 var fun1;
         2 function fun2() {
         3   console.log('我是if里面的fun2');
         4 }
         5 function fun2() {
         6   console.log('我是else里面的fun2');
         7 }
         8 console.log(typeof (fun2)); //=>function    
         9 console.log(typeof (anoymous)); //=>undefined
        10 if (true) {
        11   //这里的fun2声明被hoisting...到了顶部
        12   sayHello = function anoymous() {
        13     console.log('我是if里面的 fun1');
        14   }
        15 } else {
        16   //这里的fun2声明被hoisting...到了顶部
        17   sayHello = function anoymous() {
        18     console.log('我是else里面的 fun1');
        19   }
        20 }
        21 fun2(); // => 我是else里面的fun2   
        22 fun1(); // => 我是if里面的 fun1

    (以上内容改编自JackWang-CUMT的文章《详解Javascript 函数声明和函数表达式的区别》)

  • 相关阅读:
    js 宿主对象的属性和方法总结
    java学习路线
    (转)前端学习路线
    第11章 PADS功能使用技巧(2)-最全面
    第11章 PADS功能使用技巧(1)-最全面
    可控硅工作原理及参数详解
    光耦继电器工作原理与参数详解
    EEPROM工作原理透彻详解
    晶振工作原理及参数详解(最透彻)
    逻辑门电路详解1(最透彻)
  • 原文地址:https://www.cnblogs.com/HXW-from-DJTU/p/5983511.html
Copyright © 2011-2022 走看看