使用 RequireJS,如何传递全局对象或单例?
假设我正在主页级别编写代码,并且 2 个依赖项需要相同的对象实例,并且还将其声明为依赖项。解决这个问题的适当方法是什么?
基本上我想做的是说,“如果未加载此依赖项...则加载它。否则,使用已加载的相同实例并传递该实例。”
Let's say I am writing code at the main page level and 2 dependencies require the same instance of an object and also state that as a dependency. What is the appropriate way to go about this?
Basically what I want to do is say, "If this dependency isn't loaded... then load it. Otherwise, use the same instance that was already loaded and just pass that one."
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您可以将其设为模块级变量。例如,
You would make that a module-level variable. For example,
只需按照您的意愿为您的单例提供一个 API 即可。
并确保其延迟加载。最简单的方法是使用像 underscore 这样提供跨浏览器帮助程序的抽象库。其他选项是 ES5 Object.defineProperty 或自定义 getter/setter。
在这种情况下,
_.once
确保构造函数的结果在第一次调用后被缓存,它基本上是延迟加载它。_.once
来自下划线。Just provide an API for your singleton as you would.
And make sure its lazily loaded. The easiest way is to use an abstraction library like underscore that supplies cross browser helpers. Other options are ES5 Object.defineProperty or custom getter/setters.
In this case
_.once
ensures that constructor's result is cached after the first call, it basically lazy loads it._.once
from underscore.将 Raynos 对封装的担忧与 OP 的澄清(他希望在消息传递服务上公开一些方法)相结合,我认为正确的方法是:
Function.prototype.bind
不会存在于所有浏览器中,因此您需要包含一个类似于 Mozilla 的 polyfill提供。另一种(在我看来可能更好)方法是使消息服务对象本身成为一个模块。这看起来像
因为您向使用您的模块的每个人公开相同的
notify
和listen
方法,并且这些方法总是引用相同的 privatelistenerMap
变量,这应该执行您想要的操作。它还消除了对 Function.prototype.bind 的需要,并消除了消息传递服务本身和强制单例使用它的模块之间相当不必要的区别。Combining Raynos's concerns about encapsulation with the OP's clarification that he wants to expose a couple of methods on a messaging service, this is I think the right way to go about it:
Function.prototype.bind
will not be present in all browsers, so you would need to include a polyfill like the one Mozilla provides.An alternate (and in my opinion probably better) approach would be to make the messaging service object itself a module. This would look something like
Since you expose the same
notify
andlisten
methods to everyone who uses your module, and those always refer to the same privatelistenerMap
variable, this should do what you want. It also obviates the need forFunction.prototype.bind
, and gets rid of the rather-unnecessary distinction between the messaging service itself and the module which enforces singleton usage of it.这是一个版本,其中模块本身是共享变量,而不是该模块内的变量。
Here's a version where the module itself is the shared variable instead of a variable within that module.
作为多梅尼克答案的变体,您可以使用 'exports' magic module 自动生成模块的引用 --》添加到exports对象的属性将在模块的公共接口上,不需要返回任何值”。这避免了调用
getTheFoo()
函数来获取引用。为了解决下面的评论,我个人发现上述约定很有用。您的情况可能会有所不同,但如果您认为有用,请随意采用该惯例。该约定归结为以下两条规则:
使用文件名(例如,将 foo.js 命名为变量“foo”)会增加代码的可读性,因为大多数开发人员会将“foo”定义为 foo.js 依赖项的参数。当扫描代码或使用 grep 时,很容易找到模块内部和外部使用的所有对“foo”的引用,并且可以轻松找出模块向公众公开的内容。例如,如果 bar.js 模块中的声明反映了其他文件中的用法,则将
bar.setBarOnFoo
重命名为bar.setFooBar
会容易得多。在所有文件中简单搜索 bar.setBarOnFoo 并将其替换为 bar.setFooBar 即可完成该任务。As a variation of Domenic's answer, you can use the 'exports' magic module to automatically generate a reference for the module -- "Properties added to the exports object will be on the public interface of the module, no need to return any value." This avoids having to call the
getTheFoo()
function to obtain a reference.To address the comment below, I personally have found the above convention to be useful. Your mileage may vary, but feel free to adopt the convention if you think it is useful. The convention boils down to these two rules:
Using the name of file, e.g. for foo.js name the variable 'foo', increases the readability of the code as most developers will define 'foo' as the parameter for the foo.js dependency. When scanning the code or using grep, it is easy to find all references to 'foo' use both inside and outside the module and it makes it easy to pick out what the module is exposing to the public. For example, renaming
bar.setBarOnFoo
tobar.setFooBar
is much easier if the declaration in the bar.js module mirrors the usage in other files. A simple search and replace of bar.setBarOnFoo to bar.setFooBar across all files will accomplish the task.我处于这种情况:
由于不同的原因,我需要调用 requirejs 模块上的函数,但触发该调用的单击超出了 require 范围。
我解决这个问题的方法是创建一个 requirejs modure 来重写 window 对象。
这样,如果任何超出 require 范围的代码(我知道不应该是这种方式)都可以调用此 require 的函数来重写 window 对象。
我真的知道这不是一个“优雅”的解决方案,但在紧急情况下它可能会帮助你。
I was in this scenario:
For different reasons I needed to call a function that was on a requirejs module, but the click that fired that call was out of require.
The way I fixed this was creating a requirejs modure that writes over the window object.
This way if any piece of code that is out of the require spectrum (I know it shouldn't be this way) can call functions of this require that writes over the window object.
I really know this is not an "elegant" solution, but it may help you in case of an emergency.