IIFE单例全局未定义,除非作为窗口调用.Xyz = ilife()



为什么这个函数运行而不是用返回值初始化全局XYZ ?

"use strict";
XYZ = (function(){
    var obj = {'a':1,'b':2,'c':3};
    console.log("about to return:");
    console.log(obj);
    return obj;
    })();
 console.log(XYZ); // shows undefined

jsfiddle

似乎奇怪的是,前两个console.log返回合理的输出,然后Chrome抛出Uncaught ReferenceError: XYZ is not defined

当显式使用window.XYZ时,这工作得很好:

"use strict";
window.XYZ = (function(){
    var obj = {'a':1,'b':2,'c':3};
    console.log("about to return:");
    console.log(obj);
    return obj;
    })();
 console.log(XYZ); // shows a:1, b:2, c:3

如果"use strict;"被移除,则将工作。但是不要那样做——继续读。

严格模式防止XYZ = ...成为新的全局变量。

John Resig在他对严格模式的概述中解释道:

尝试在foo没有定义的地方赋值foo = "bar";将会导致失败。对象的foo属性赋值全局对象(例如window.foo),现在它只是抛出一个异常。这一定会抓住一些烦人的bug。

window.XYZ = IIFE()的代码在严格模式下工作,因为这里的赋值是对现有对象window的属性。

对于许多应用程序来说,使用window.XYZ可能"足够好",但是您可能会遇到在包管理器中使用window.XYZ"短路"依赖管理的平台(例如Meteor)。在这种情况下,严格模式可以在IIFE中启用,但不能在页面级别启用。

要使用严格模式,将一个单例IIFE赋值给一个新的全局变量,只在IIFE的第一行打开严格模式。

XYZ = (function() {
  "use strict";
  var obj = {
    'a': 1,
    'b': 2,
    'c': 3
  };
  console.log("about to return:");
  console.log(obj);
  return obj;
})();
console.log(XYZ);

警告:"use strict;",因为第二行没有启用严格模式:

不要这样做:

XYZ = 0;
"use strict";
XYZ = ...

您可以通过查看this没有显式设置的函数中的this来测试是否启用了严格模式。当严格模式为true时,取消设置时thisnull,当严格模式为false时,thiswindow

参见:use strict"在JavaScript中做什么,背后的原因是什么?

最新更新