以下JS语法有何区别?

7

以下是两种定义BW.Timer的方法。有人可以告诉我它们之间的区别吗?我不确定第一种方法是否有效,但如果有效,使用myfunc=(function(){}())语法有何不同?

BW.Timer = (function () {
    return {
        Add: function (o) {
            alert(o);
        },
        Remove: function (o) {
            alert(o);
        }
    };
} ());

并且...

BW.Timer = function () {
    return {
        Add: function (o) {
            alert(o);
        },
        Remove: function (o) {
            alert(o);
        }
    };
};

1
这两个片段不相等 - 顶部将IIFE的返回值分配给BW.Timer,而底部只是将一个函数(与第一个示例中立即执行的相同函数)分配给BW.Timer - jbabey
你是否对结果进行了基本的日志记录?如果有,你会发现第一个确实是有效的,并且它们具有不同的结果。在StackOverflow上有数百个与该函数语法相关的问题。 - I Hate Lazy
1
第一个代码片段使用立即调用函数表达式(IIFE)。 - apsillers
3个回答

9

第一种是立即调用函数的返回值。第二种是一个函数。它的本质在于这两者之间的区别:

var f = (function() { return 0; })();

var f = function() { return 0; };

因为第一个函数被立即调用,所以变量f被赋值为0。第一个f不是一个函数。然而,我们必须调用第二个f才能获得它的值:

f(); // 0

因此,在您的示例中,第一个BW.Timer是对象字面量本身,而第二个是返回对象字面量的函数。您必须调用该函数才能访问该对象:

BW.Timer().Add(x);

为什么要使用前者?

你可能会问自己,为什么要使用像a = (function() { return {}; })()这样的语法,而不是a = {},但有一个很好的理由。IIFE(立即调用的函数表达式)与常规函数不同,允许模拟静态变量(在单个实例中保持其值的变量)。例如:

var module = (function() {
    var x = 0;

    return {   get: function()  { return x },
               set: function(n) { x = n }
    };

})();

上述内容是模块模式的典型案例。由于函数立即调用,变量x被实例化,并且返回值(即对象)被赋给了module。除非使用为我们提供的getset方法,否则我们无法访问变量x。因此,x是静态的,这意味着每次使用module时,它的变量都不会被覆盖。
module.set(5);

module.get(); // 5

另一方面,让我们看一个把module声明为函数的例子:
// assume module was made as a function

module().set(5);

module().get(); // 0

每次调用module()函数时,变量x都会被覆盖。因此,我们实际上是在每次调用module()时使用不同的modulex实例。


3
差别相当大。
在第一种情况下,当遇到BW.Timer时,它会被执行,并且静态版本会被分配给BW.Timer。在这种情况下,可以使用BW.Timer.Add(1)。每次调用BW.Timer都将是相同的对象。
在第二种情况下,当第一次遇到BW.Timer时,它不会被执行,而是一个函数引用,必须调用BW.Timer()。为了使用Add,必须这样做BW.Timer().Add(1)。还可以发出var timer = new BM.Timer();。每个BW.Timer()实例在这里将是唯一的。

2
在第一个例子中,BW.Timer 引用了自执行函数返回的对象,而在第二个例子中它引用了一个函数对象,换句话说,它是一个可以被执行的函数 BW.Timer()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接