【问题标题】:Declaring functions in JavaScript [duplicate]在 JavaScript 中声明函数 [重复]
【发布时间】:2010-12-27 21:54:45
【问题描述】:

可能重复:
Javascript: var functionName = function() {} vs function functionName() {}

这两种声明函数的方式有什么区别?

function someFunc() { ... }

var someFunc = function() { ... }

我不是在技术意义上问。我不是在问哪种风格更便于阅读,或者哪种风格更受欢迎。

【问题讨论】:

标签: javascript syntax function


【解决方案1】:

使用function someFunc() { ... } 的一个优点是函数名出现在Firebug 调试器中。以其他方式声明的函数 (var someFunc = function() { ... }) 以匿名的形式出现。

【讨论】:

    【解决方案2】:

    实际上,不同之处在于第二个声明使我们能够像这样声明函数,从而可以将函数作为对象的属性:

    var myObject=new Object();
    myObject.someFunc=function() { ... }; 
    

    【讨论】:

      【解决方案3】:

      当你写作时

      function Test() {
      }
      

      JavaScript 实际上是在创建一个属性,它分配给函数对象,一旦调用该函数对象,就会执行函数定义中报告的代码。该属性附加到对象window,或附加到包含函数定义的对象。

      【讨论】:

      • 您在这里有一些误解:首先,JavaScript 中的命名函数和匿名函数之间存在区别,正如您在函数上调用 toString 所看到的那样。其次,虽然函数声明确实为当前变量对象添加了一个属性,但这只是全局代码中的全局对象(在浏览器中也称为window)(而不是在函数内部,例如)。结果,您的第三段是完全错误的。 (续...)
      • ... 第三,将函数分配给变量对象的时间有所不同。由函数声明(例如function test() {})创建的函数可以在出现在它之前的代码中使用,这不适用于由函数表达式声明的函数(例如var test = function() {};
      • 这不是“JavaScript:权威指南”中报道的内容,它明确指出“当 JavaScript 解析器遇到函数定义时,它会解析并存储(不执行)构成函数体的内容. 它定义了一个属性(如果函数定义与另一个函数嵌套,则在调用对象中;否则,在全局对象中)与保存该函数的函数同名。
      • 我删除了不正确的部分。关键是在这两种情况下,JavaScript 解释器都会创建一个属性。从技术上讲,正如 OP 所要求的那样,没有区别。
      • 我不确定您不同意我的哪些观点。哪一个?关于你现在的回答,我的第一点仍然成立。我的第二点似乎仍然存在,因为函数体内的函数声明不会成为全局对象的属性。我的第三点仍然存在,因为它指出了您的答案未提及的函数声明和函数表达式之间的区别。
      【解决方案4】:

      我与这里的大多数人意见不同。 从技术上讲,这种语法对于两种方式声明函数可能意味着相同我的上一个陈述不正确。我在一篇差异文章中阅读了为什么它们在技术上存在差异,我会在最后补充一下,为什么) ;但它们在演变模式中发挥作用的方式是巨大的。我强烈推荐 Doughlas Crockford 的“Javascript: The Good Parts”。

      但是要以一种微妙而简单的方式来证明我的观点;这是一个小例子。

      //Global function existing to serve everyone
      function swearOutLoud(swearWord) {
          alert("You "+ swearWord);           
      }
      //global functions' territory ends here
      
      //here is mr. spongebob. He is very passionate about his objects; but he's a bit rude.
      var spongeBob = {
          name : "squarePants",
          swear : function(swearWord) {
                      name = "spongy";
                      alert("You "+ swearWord);
                      return this;
                  }
      }
      
      //finally spongebob learns good manners too. EVOLUTION!
      spongeBob.apologize = function() {
          alert("Hey " + this.name + ", I'm sorry man!");
          return this;
      }
      
      
      //Ask spongebob to swear and then apologize in one go (CASCADING EFFECT!!)
      alert(spongeBob.swear("twit").apologize());
      

      如果您查看上面的代码,我声明了一个名为 swearOutLoud 的函数。它将从任何对象或电话中获取一个脏话,并为您提供输出。它可以使用传递给它的“this”参数和参数对任何对象进行操作。

      然而,第二个声明被声明为名为“海绵宝宝”的对象的属性。这一点很重要;在这里,我正朝着对象驱动的行为迈进。虽然我也保持“级联效应”,因为如果我没有其他东西可以返回,我会返回“this”。

      类似的东西是在 jquery 中完成的;如果您正在尝试编写框架或其他东西,这种级联模式很重要。您还将它链接到 Builder 设计模式。

      但是通过将函数声明为对象的属性,我能够实现以对象为中心的行为,从而产生更好的编程范式。除非设计得好;在外部声明的具有全局访问权限的单个函数会导致非面向对象的编码方式。不知何故,我更喜欢后者。

      要查看级联效果,请查看最后一条语句,您可以在其中要求海绵宝宝立即发誓并道歉;尽管后来添加了“道歉”作为属性。

      我希望我能说清楚。从技术角度来看,差异可能很小;但从设计和代码演变的角度来看,它是巨大的,并且让世界变得与众不同。

      但那只是我!要么接受,要么离开它。 :)

      编辑:

      所以这两个调用在技术上是不同的;因为命名声明绑定到全局命名空间并在解析时定义。所以甚至可以在函数声明之前调用。

       //success
       swearOutLoud("Damn");
      
      function swearOutLoud(swearWord) {
          alert("You " + swearWord)
      }
      

      上面的代码可以正常工作。但下面的代码不会。

      swear("Damn!");
          var swear = function(swearWord) {
          console.log(swearWord);
      }
      

      【讨论】:

      • 这里的主要部分不清楚,与问题无关。
      • 也许,但另一方面,海绵宝宝在和你说话
      【解决方案5】:

      为了可读性,我想说第一个显然更好。未来的维护程序员,即使假设他们对 javascript 足够熟悉,知道这个线程中出现的许多更精细的点,也会假设第一种格式。

      例如,如果他们有一天想要按 ctrl-f 搜索您的函数的定义以查看其中发生了什么,他们会先搜索 someFunc = function() 还是 function someFunc()

      此外,为了彻底排版(因为我们正在谈论可读性),读者通常会快速浏览文本,如果他们正在寻找以“var”开头的行,他们更倾向于跳过函数定义。

      我知道这是一个非技术性的答案,但人类阅读代码比计算机更难。

      【讨论】:

        【解决方案6】:

        另一个区别是,在大多数浏览器上,后者允许您根据情况定义不同的实现,而前者不会。假设您想要跨浏览器事件订阅。如果您尝试这样定义addEventListenerTo 函数:

        if (document.addEventListener) {
            function addEventListenerTo(target, event, listener) {
                ....
            }
        } else if (document.attachEvent) {
            function addEventListenerTo(target, event, listener) {
                ....
            }
        } else {
            function addEventListenerTo(target, event, listener) {
                ....
            }
        }
        

        在某些浏览器上,所有函数最终都会被解析,最后一个优先。结果:以上只是行不通。但是,将匿名函数分配给变量是可行的。您还可以使用分配给变量的匿名函数来应用函数式和基本的aspect oriented programming 技术。

        var fib = memoize(function (n) { 
            if (n < 0) return 0;
            if (n < 2) return 1;
            return fib(n-1) + fib(n-2); 
        });
        
        ...
        // patch the $ library function
        if (...) {
            $ = around($, fixArg, fixResult);
        }
        

        【讨论】:

          【解决方案7】:

          第一种形式都是真的:

          function test() { }
          

          是一种比较公认的语法,即第二种形式:

          var test = function() { ... }
          

          允许您控制函数的范围(通过使用 var;没有它,无论如何它都是全局的)。

          你甚至可以两者兼得:

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

          这允许您以第二种形式定义递归函数。

          【讨论】:

          • 我不同意第一种形式是更公认的语法,而第二种形式。它们只是不同的形式,其中btoh是常用的。此外,命名函数表达式(这是您在最后一个示例中使用的)在 IE 中具有奇怪的行为。请参阅以下文章:yura.thinkweb2.com/named-function-expressions
          【解决方案8】:

          第二个例子的风格更符合其他常见的函数声明方式,因此可以说它更具可读性

          this.someFunc = function() { ... }
          ...
          someFunc: function() { ... },
          

          但是,如前所述,它是匿名的,因此在分析时不会出现该名称。 声明函数的另一种方法如下,它可以让你两全其美

          var someFunc = function someFunc() { ... }
          

          【讨论】:

            猜你喜欢
            • 2012-06-17
            • 1970-01-01
            • 1970-01-01
            • 2018-01-06
            • 2022-01-16
            • 2010-11-08
            • 1970-01-01
            相关资源
            最近更新 更多