【问题标题】:What is the difference between two declarations of module in javascript?javascript中两个模块声明有什么区别?
【发布时间】:2026-02-17 00:30:01
【问题描述】:

在 JavaScript 中两个模块声明有什么区别? 一个在函数周围有括号,另一个没有?

一篇文章这么说

注意匿名函数周围的 ()。这是要求 语言,因为以记号函数开头的语句是 总是被认为是函数声明。包括 () 创建一个 而是函数表达式。

检查时两者似乎都做同样的事情。

var person = (function () {
    // Private
    var name = "Robert";
    return {
        getName: function() {
            return name;
        },
        setName: function(newName) {
            name = newName;
        }
    };
}());

var person = function () {
    // Private
    var name = "Robert";
    return {
        getName: function() {
            return name;
        },
        setName: function(newName) {
            name = newName;
        }
    };
}();

【问题讨论】:

标签: javascript module iife


【解决方案1】:

JavaScript 中的函数有两种类型 - 声明和表达式。

这是两者的区别:

  1. 函数声明被提升。这意味着您可以在函数出现在程序中之前调用它,因为 JavaScript 中的声明被提升
  2. 可以立即调用函数表达式。函数声明不能​​。这是因为表达式 express(或返回值)。函数表达式表达一个函数。

函数声明示例:

foo("bar");

function foo(bar) {
    alert("foo" + bar);
}

上面的程序可以运行,因为foo 是一个函数声明。

foo("bar"); // throws an error, foo is undefined - not a function

var foo = function (bar) {
    alert("foo" + bar);
};

上述程序将无法工作,因为foo 被声明为undefined,被提升,然后分配了函数表达式的值。因此它被调用时是undefined

函数表达式示例:

(function (bar) {
    alert("foo" + bar);
}("bar"));

上面的函数将立即被调用,因为它是一个函数表达式。

function (bar) {
    alert("foo" + bar);
}("bar"); // throws an error, can't call undefined

上面的函数不会被立即调用,因为它是一个函数声明。请记住,声明不表达(或返回值)。所以这就像试图将undefined 作为一个函数来调用。

函数如何变成表达式?

如果在预期表达式的上下文中使用函数,则将其视为表达式。否则视为声明。

表达式应满足以下条件:

  1. 您正在为变量赋值(即identifier = expression)。
  2. 括号内(即( expression ))。
  3. 作为运算符的操作数(即operator expression)。

因此以下都是函数表达式:

var foo = function () {};
(function () {});
~function () {};

其他的都是函数声明。简而言之,如果你的函数前面没有任何东西,它就是一个声明。

查看此代码:https://github.com/aaditmshah/codemirror-repl/blob/master/scripts/index.js#L94

下面的函数isExpression用于测试任意JavaScript代码是否为表达式:

function isExpression(code) {
    if (/^\s*function\s/.test(code)) return false;

    try {
        Function("return " + code);
        return true;
    } catch (error) {
        return false;
    }
}

希望这能消除您心中的疑虑。

简而言之:

  1. 函数表达式表达或返回一个值(在本例中为函数)。因此它可以立即被调用,但在它出现在程序中之前不能被调用。
  2. 函数声明被提升。因此它可以在它出现在程序中之前被调用。但是,由于它不表达任何值,因此不能立即调用。

【讨论】:

    【解决方案2】:

    不同的是写的时候:

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

    使用(多余但有用的)分组() 是一种常见的编码风格,可以从第一行中清楚地看出右侧很可能是立即调用的函数表达式(IIFE)。但是,在第二个中:

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

    直到你读到最后一行才变得明显,这可能是好几行。直到你读到最后一行,你可能认为你正在阅读一个简单的作业:

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

    请注意,括号也可以用于简单的赋值:

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

    但在这种情况下,它们确实是多余的(并且可能由于将它们用于 IIFE 的惯例而产生误导)。

    An Important Pair of Parens

    【讨论】:

      【解决方案3】:

      在当前上下文中,解释器没有区别。通常最好的编写模块的方法是用括号包裹函数:

      var person = (function () {
          // Private
          var name = "Robert";
          return {
              getName : function () {
                  return name;
              }
          };
      }());
      

      那是因为语法更简洁,很明显你想在函数声明后立即调用它。还有一个原因是:

      (function () {
          //some stuff
      }());
      

      会起作用,但是

      function () {
          //some stuff
      }();
      

      这不会。

      每次使用常见的编码风格时都包装函数,这通常是一件好事:-)。

      【讨论】: