javascript - 如何在其他 JS 文件/模块中调用/使用该模块

标签 javascript function design-patterns

我最近阅读了一些 JS 模块设计模式。我遇到了这个小代码片段,如下所示。

(function(window) {
    var Module = {
        data: "I'm happy now!"
    };

    window.Module = Module;
})(window);

还是不太明白这段代码,我的问题是:

  • 如何在这个特定的 JS 文件之外使用/调用这个模块?需要我 给这个模块分配一个变量?例如var module1 = (...)(...);
  • 谁能解释一下这里的 window 参数代表什么?
  • 在项目中包含两/三个这样的模块是一种好习惯吗? 同一个文件?

最佳答案

在这种情况下创建匿名函数的主要原因是为了防止全局对象污染。这不是真正的模块模式。

当你声明一个变量时,问题就出现了。如果没有函数范围,变量将被添加到全局对象(窗口)中。如果您要在函数中声明变量。它会将变量添加到函数范围内,而不会污染全局对象窗口。

发生的情况是,一个 javascript 文件可以添加一个名为 foo 的变量,并在另一个文件上使用名为 foo 的变量。除非你真的想让两个 javascript 文件共享一个变量,否则它可能会产生难以修复的冲突和错误。

例如:a.js

var foo = "one"

b.js

var foo = "two"

c.js

alert(foo)

在这种情况下,警报框可能会显示“一”或“二”,具体取决于包含的 javascript 文件中的顺序。

但是有了这个 a.js:

(function () {
    var foo = "one"
})()

b.js

(function () {
    var foo = "two"
})()

c.js

(function () {
    alert(foo)
})()

这会产生一个错误,因为您不能 alert 未声明的变量。

检测 undefined variable 的一种方法是确保以严格模式执行javascript代码。

为此,请在文件或函数的顶部添加字符串 "use strict"

function () {
  "use strict"
  ...
}

未声明的变量会引发错误,应该可以通过这种方式修复代码。

此外,如果您忘记使用 var 关键字声明变量,即使代码的作用域是函数,它也可能最终将变量添加到全局作用域。防止全局范围污染的唯一方法是在严格模式下运行代码。

在您提供的代码片段中,名为 Module 的模块被显式添加到窗口对象中。您可以从 javascript 中的任何位置访问窗口对象,除非窗口名称被其他变量隐藏。

现在,回到模块。如果要定义模块,可以通过多种方式完成。例如,您可以在称为模块的窗口对象上创建一个对象。在此对象中,您将插入您的模块。

模块.js

window.modules = {}

foo.js

(function (window) {
  var module = {}
  ...
  window.modules.foo = module
})(window)

这种变体不是很好,因为您必须手动将模块添加到 modules 对象。您必须手动修改窗口对象,这可能会出错。

modules.js

window.modules = {}

function define(name, constructor) {
  var module = {exports: {}}
  constructor(module)
  window.modules[name] = module.exports
}

function require(name) {
  return window.modules[name]
}

foo.js

define("foo", function (module) {
  module.exports.one = function () {
    return 1
  }

  module.exports.plus = function (a, b) {
    return a + b
  }
})

bar.js

define("bar", function (module) {
  module.exports = function () {
    var foo = require("foo")
    return foo.plus(foo.one(), foo.one())
  }
})

这是一个模块定义,看起来有点像用 http://requirejs.org/ 定义的模块。 .这是非常基本的,因为它没有考虑模块依赖关系,所以如果 barfoo 之前加载和使用。那么 require 方法将无法返回模块。

另外,如果你想存储模块而不让它们在全局范围内可见,你只能在窗口对象上定义 requiredefine 方法并隐藏模块进入这样的匿名范围:

  (function (window) {
    var modules = {}

    function define(name, constructor) {
      var module = {exports: {}}
      constructor(module)
      modules[name] = module.exports
    }

    function require(name) {
      return modules[name]
    }

    window.define = define
    window.require = require
  })(window)

这样,definerequire 是唯一可以让您访问模块的函数。其他模块将无法修改其他模块而不需要它们。这在使用可能与您的模块系统冲突的第三方脚本时很有用。

关于javascript - 如何在其他 JS 文件/模块中调用/使用该模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32100376/

相关文章:

c - C语言中被调用(派生)函数如何访问调用者(基)函数的变量?

swift - Swift 中没有带有标识符错误的 Segue?

javascript - 未捕获的类型错误 : Cannot set property 'value' of null with custom element

javascript - 我想删除 Anythingslider 中的开始/停止按钮,但保留其余的导航

javascript - 在页面加载时通过 JQUERY 获取 SelectList 值

javascript - 重构查找函数

javascript - 枚举对象作为字典键

c# - 在 C# 中存储设置的设计模式

design-patterns - 学习设计模式的学生的实践任务

design-patterns - 观察者模式 : Avoiding bad re-entrant behavior?