search

Home  >  Q&A  >  body text

javascript - JS这两种写法有什么不同

1

var getLength = (function(){
               .....
   })();

2

  function getLength (){
                    .....
    }
ringa_leeringa_lee2894 days ago759

reply all(7)I'll reply

  • 天蓬老师

    天蓬老师2017-04-10 12:47:37

    // 写法1
    var getLength = function(){
        .....
    };
    // 写法2
    function getLength (){
        .....
    }
    

    我觉得你想问的应该是这两种写法的区别是什么。

    从执行的时候效果来看,两种写法都可以通过 getLength() 这种方式来调用去执行。

    但是实际上这两种写法是不一样的。

    写法1

    我暂时给这种写法取个名字:变量声明及函数表达式的引用赋值。

    写法1中包含了三层意思

    1. 声明一个变量 getLength
    2. 声明一个匿名函数
    3. 变量 getLength 赋值为匿名函数的引用

    就是说,写法1中的“函数声明”是在代码执行期——代码执行的时候——去“声明”的。

    如果你想要执行 getLength(),就必须在该行代码执行以后才能成功调用。

    例如

    getLength();  // 在赋值前执行
    // TypeError: undefined is not a function
    // 语法分析阶段不会报错,当代码执行到上面时,就会报 TypeError,因为 getLength 尚未赋值
    
    var getLength = function(){
                       .....
    };
    
    

    写法2

    写法2 可以是正宗的函数声明。

    其作用就是声明一个名为 getLength 的函数。

    函数声明是在语法分析阶段就已经完成(代码执行前)。故我们可以这样

    getLength();  // 完全OK
    
    function getLength(){
             .....
    };
    

    语法糖?

    不是语法糖,不是语法糖。

    前文已经分析过,这两种书写方式对解释器来说是在不同阶段完成对函数的“声明”。

    一个是在代码执行期完成“声明”,一个是在语法分析阶段完成声明。

    // 例如下面的代码是用来获取函数的函数名,我们可以发现两种方式声明的函数是不一样的
    var f = function() { console.log(arguments.callee.name) }
    f();
    // 此时返回 "" (空字符串)
    
    function f() { console.log(arguments.callee.name) }
    f();
    // 此时返回 "f"
    

    应用场景

    一般场景下,两种都能用。用法也差不多。只不过函数表达式赋值方式需要前置,而函数声明可以后置。

    如果需要函数自己引用自己,这个时候推荐使用函数声明。因为 arguments.callee 在 ES5 strict mode 是禁用的。

    例如

    function F(n) {
      if(n < 1) {
        return 1   
      }
      return F(n-1) + n;
    }
    

    如果是对象的方法声明,可以使用函数表达式赋值的方式。

    例如

    var obj = {
      getValue : function() {return 'obj';}
    }
    

    又或者你要延迟声明函数,或者动态修改函数内容,可以使用函数表达式赋值方式。

    其他场景,怎么舒服怎么用呗。

    PS

    文中用引号包裹起来的声明其效果就是赋值。

    var getLength = (function(){
        .....
    })();
    

    关于作者原文中的这个函数。用一句话概括。

    声明一个变量 getLength,并将一个匿名函数的返回值赋值给他。

    reply
    0
  • 怪我咯

    怪我咯2017-04-10 12:47:37

    如果你了解面向对象思想的话,前者是js以类的形式表示,后者是以面向过程的的方式展示。

    reply
    0
  • ringa_lee

    ringa_lee2017-04-10 12:47:37

    最近在拜读《JavaScript语言精粹》。书中113页相关内容如下:

    function语句对比function表达式

    JavaScript既有function语句,同时也有function表达式。这令人困惑,因为它们看起来好像就是相同的。一个function语句就是其值为一个函数的var语句的速记形式。

    下面的语句:

      function foo() {}
    

    意思相当于:

      var foo = function foo() {};
    

    在整本书中,我一直使用的是第2种形式,因为它能明确表示foo是一个包含一个函数值的变量。要用好这门语言,理解函数就是数值是很重要的。

    function语句在解析时会发生被提升的情况。这意味着不管function被放置在哪里,它会被移动到被定义时所在作用域的顶层。这放宽了函数必须先声明后使用的要求,而我认为这会导致混乱。在if语句中使用function语句也是被禁止的。结果表明大多数的浏览器都允许在if语句里使用function语句,但它们在解析时的处理各不相同。这就造成了可移植性的问题。

    一个语句不能以一个函数表达式开头,因为官方的语法假定以单词function开头的语句是一个function语句。解决方法时把函数调用括在一个圆括号之中。

      (function () {
          var hidden_variable;
    
          //这个函数可能对环境有一些影响,但不会引入新的全局变量。
      }());
    

    reply
    0
  • PHPz

    PHPz2017-04-10 12:47:37

    第一种情况getLength的值是自运行匿名函数返回的值,而不是函数;第二种情况getLength才是函数。

    reply
    0
  • PHP中文网

    PHP中文网2017-04-10 12:47:37

    不同意见 @HJin.me

    方法一

    var getlength = (function(){console.log("run")})()

    申明一个getlength变量,但是并没有给它赋值

    (function(){})() 是一个立即执行的函数

    getlength 能得到的是这个匿名函数的返回值

    不认同你所说的变量 getLength 赋值为匿名函数的引用

    如果是引用那么getlength() 就应该是个可执行的函数

    但是考虑下

    var getlength = (function(){
        console.log("this is a test");
    })()
    

    对getlength typeof 发现会是一个undefined

    reply
    0
  • 大家讲道理

    大家讲道理2017-04-10 12:47:37

    @HJin.me 回答的非常棒!但是有一点补充一下,就是即使在 ES5 strict mode 下,要调用自己也是可以用匿名函数的方式的:

    var a = 0,
        b = 111,
        c = function b() {
          if (a == 2) {return}
          a++
          b()
        }
    
    c()
    

    最终 a == 2 && b == 111

    如果在函数 b 外部调用 b() ,会报错说:"TypeError: number is not a function"

    这样的写法也可以用于 shim JavaScript 在低级浏览器下没有 .name 属性的困境,通过将函数 .toString() 然后通过正则表达式就能够提取出函数的名称了。

    reply
    0
  • 巴扎黑

    巴扎黑2017-04-10 12:47:37

    简单来说 function fun() 这种方法声明的函数全局可用,在声明的前面也可以用 具有预载特性,第二种 fun=function() 要执行了之后才能被访问, 一般我推荐前者声明比较多,而后者看出js的概念和灵活性

    reply
    0
  • Cancelreply