如何call/use这个模块在其他JS中files/modules
How to call/use this module in other JS files/modules
最近看了一些JS模块设计模式。我遇到了下面这个小代码片段。
(function(window) {
var Module = {
data: "I'm happy now!"
};
window.Module = Module;
})(window);
还是不太理解这段代码,我的问题是:
- 如何use/call这个模块在这个特定的JS文件之外?需要我
为这个模块分配一个变量?例如var module1 = (...)(...);
- 谁能解释一下这里的 window 参数代表什么?
- 在 two/three 这样的模块中有一个好的做法吗?
同一个文件?
实际上这不是一个模块,而是一个自调用匿名函数或一个立即函数,它在参数中获取一个对象并为其分配 Module
属性:
页面window
是传递给这个函数的参数。
所以一个名为 Module
的对象包含 data
属性 被分配给 window.
JavaScript 自调用函数:
A self-invoking expression is invoked (started) automatically, without being called.
Function expressions will execute automatically if the expression is
followed by ()
.
You cannot self-invoke a function declaration.
You have to add parentheses around the function to indicate that it is
a function expression
因此,正如您所看到的,无法调用即时函数,因为它的名称表明它将立即执行并且由其自身执行,没有其他函数或范围可以执行它。
要获得更好的参考,请查看:
- Javascript Self Invoking Functions.
- Self-Invoking Functions section in JavaScript Function Definitions.
关于你最后一个关于它的好处和良好做法的问题,如给定 Article reference 所示:
在哪里使用自执行函数?
One obvious situation is when you want to auto-run a function like I
showed in above example but that is trivial. If you are in a situation
where you want to run a piece of code repeatedly like updating
something in the database based on user interaction or fetching
records from database every 10 seconds or you want to load new stories
via ajax
similar to how facebook does on its homepage or some other
similar situation, one would normally go for setInterval
function
something like this:
setInterval(doStuff, 10000);
Above, doStuff
function will get called every 10 seconds. That is the
normal approach most developers seem to go with. However, there is a
huge problem with that.
The setInterval
will call doStuff function exactly at specified time of 10 seconds again and again irrespective
of whether doStuff function actually finished doing what it is
supposed to do. That is bad and will certainly get you into unexpected
results.
That is one example of where setInterval
is "bad" and should be
avoided.
This is exactly where self-executing functions come in handy. We can
do the same task with the help of self-executing function along with
setTimeout
like this:
function foo(){
// your other code here
setTimeout(foo, 10000);
}();
This code will also repeat itself again and again with one difference.
setTimeout
will never get triggered unless doStuff
is finished. A much
better approach than using setInterval
in this situation.
从另一个文件调用它:
如果这个函数在另一个文件上,如果包含这个文件,它将被自动调用。
为什么我们在JavaScript中使用自调用函数?
如果你问自己为什么要使用这些函数,自调用函数是用来管理Variable Scope.
查看 answer here 了解更多信息。
本例中创建匿名函数的主要原因是为了防止全局对象污染。这不是真正的模块模式。
声明变量时出现问题。如果没有函数范围,变量将被添加到全局对象 (window)。如果要在函数中声明变量。它会在不污染全局对象的情况下将变量添加到函数作用域 window.
发生的情况是 javascript 文件可以添加一个名为 foo
的变量,而在另一个文件上也使用该名为 foo
的变量。除非你真的想让两个 javascript 文件共享一个变量,否则它可能会产生难以修复的冲突和错误。
例如:a.js
var foo = "one"
b.js
var foo = "two"
c.js
alert(foo)
在这种情况下,警告框可能会显示 "one" 或 "two",具体取决于包含 javascript 文件的顺序。
但是有了这个a.js:
(function () {
var foo = "one"
})()
b.js
(function () {
var foo = "two"
})()
c.js
(function () {
alert(foo)
})()
这会产生错误,因为您不能 alert
一个未声明的变量。
检测未定义变量的一种方法是确保在严格模式.
下执行javascript代码
为此,在文件或函数的顶部添加字符串 "use strict"
。
function () {
"use strict"
...
}
未声明的变量会引发错误,应该可以通过这种方式修复代码。
此外,如果您忘记使用 var
关键字声明变量,即使代码在函数范围内,它也可能最终将变量添加到全局范围。防止全局范围污染的唯一方法是 运行 严格模式下的代码。
在您提供的代码片段中,名为 Module 的模块被显式添加到 window 对象中。您可以从 javascript 中的任何位置访问 window 对象,除非 window 名称被其他变量隐藏。
现在,回到模块。如果要定义modules,可以通过多种方式来完成。例如,您可以在 window 对象上创建一个名为模块的对象。在此对象中,您将插入您的模块。
module.js
window.modules = {}
foo.js
(function (window) {
var module = {}
...
window.modules.foo = module
})(window)
这个变体不是很好,因为您必须手动将模块添加到 modules
对象。您必须手动修改 window 对象,这可能会出错。
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/ 定义的模块。这是非常基本的,因为它没有考虑模块依赖性,所以如果 bar
在 foo
之前加载和使用。然后 require
方法将无法 return 模块。
此外,如果你想存储模块而不让它们在全局范围内可见,你只能在 window 对象上定义 require
和 define
方法并隐藏模块进入这样的匿名范围:
(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)
这样,define
和 require
是唯一可以让您访问模块的函数。如果不首先要求其他模块,其他模块将无法修改其他模块。这在使用可能与您的模块系统冲突的第三方脚本时很有用。
最近看了一些JS模块设计模式。我遇到了下面这个小代码片段。
(function(window) {
var Module = {
data: "I'm happy now!"
};
window.Module = Module;
})(window);
还是不太理解这段代码,我的问题是:
- 如何use/call这个模块在这个特定的JS文件之外?需要我 为这个模块分配一个变量?例如var module1 = (...)(...);
- 谁能解释一下这里的 window 参数代表什么?
- 在 two/three 这样的模块中有一个好的做法吗? 同一个文件?
实际上这不是一个模块,而是一个自调用匿名函数或一个立即函数,它在参数中获取一个对象并为其分配 Module
属性:
页面
window
是传递给这个函数的参数。所以一个名为
Module
的对象包含data
属性 被分配给 window.
JavaScript 自调用函数:
A self-invoking expression is invoked (started) automatically, without being called.
Function expressions will execute automatically if the expression is followed by
()
.You cannot self-invoke a function declaration.
You have to add parentheses around the function to indicate that it is a function expression
因此,正如您所看到的,无法调用即时函数,因为它的名称表明它将立即执行并且由其自身执行,没有其他函数或范围可以执行它。
要获得更好的参考,请查看:
- Javascript Self Invoking Functions.
- Self-Invoking Functions section in JavaScript Function Definitions.
关于你最后一个关于它的好处和良好做法的问题,如给定 Article reference 所示:
在哪里使用自执行函数?
One obvious situation is when you want to auto-run a function like I showed in above example but that is trivial. If you are in a situation where you want to run a piece of code repeatedly like updating something in the database based on user interaction or fetching records from database every 10 seconds or you want to load new stories via
ajax
similar to how facebook does on its homepage or some other similar situation, one would normally go forsetInterval
function something like this:
setInterval(doStuff, 10000);
Above,
doStuff
function will get called every 10 seconds. That is the normal approach most developers seem to go with. However, there is a huge problem with that.The
setInterval
will call doStuff function exactly at specified time of 10 seconds again and again irrespective of whether doStuff function actually finished doing what it is supposed to do. That is bad and will certainly get you into unexpected results.That is one example of where
setInterval
is "bad" and should be avoided.This is exactly where self-executing functions come in handy. We can do the same task with the help of self-executing function along with
setTimeout
like this:
function foo(){
// your other code here
setTimeout(foo, 10000);
}();
This code will also repeat itself again and again with one difference.
setTimeout
will never get triggered unlessdoStuff
is finished. A much better approach than usingsetInterval
in this situation.
从另一个文件调用它:
如果这个函数在另一个文件上,如果包含这个文件,它将被自动调用。
为什么我们在JavaScript中使用自调用函数?
如果你问自己为什么要使用这些函数,自调用函数是用来管理Variable Scope.
查看 answer here 了解更多信息。
本例中创建匿名函数的主要原因是为了防止全局对象污染。这不是真正的模块模式。
声明变量时出现问题。如果没有函数范围,变量将被添加到全局对象 (window)。如果要在函数中声明变量。它会在不污染全局对象的情况下将变量添加到函数作用域 window.
发生的情况是 javascript 文件可以添加一个名为 foo
的变量,而在另一个文件上也使用该名为 foo
的变量。除非你真的想让两个 javascript 文件共享一个变量,否则它可能会产生难以修复的冲突和错误。
例如:a.js
var foo = "one"
b.js
var foo = "two"
c.js
alert(foo)
在这种情况下,警告框可能会显示 "one" 或 "two",具体取决于包含 javascript 文件的顺序。
但是有了这个a.js:
(function () {
var foo = "one"
})()
b.js
(function () {
var foo = "two"
})()
c.js
(function () {
alert(foo)
})()
这会产生错误,因为您不能 alert
一个未声明的变量。
检测未定义变量的一种方法是确保在严格模式.
下执行javascript代码为此,在文件或函数的顶部添加字符串 "use strict"
。
function () {
"use strict"
...
}
未声明的变量会引发错误,应该可以通过这种方式修复代码。
此外,如果您忘记使用 var
关键字声明变量,即使代码在函数范围内,它也可能最终将变量添加到全局范围。防止全局范围污染的唯一方法是 运行 严格模式下的代码。
在您提供的代码片段中,名为 Module 的模块被显式添加到 window 对象中。您可以从 javascript 中的任何位置访问 window 对象,除非 window 名称被其他变量隐藏。
现在,回到模块。如果要定义modules,可以通过多种方式来完成。例如,您可以在 window 对象上创建一个名为模块的对象。在此对象中,您将插入您的模块。
module.js
window.modules = {}
foo.js
(function (window) {
var module = {}
...
window.modules.foo = module
})(window)
这个变体不是很好,因为您必须手动将模块添加到 modules
对象。您必须手动修改 window 对象,这可能会出错。
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/ 定义的模块。这是非常基本的,因为它没有考虑模块依赖性,所以如果 bar
在 foo
之前加载和使用。然后 require
方法将无法 return 模块。
此外,如果你想存储模块而不让它们在全局范围内可见,你只能在 window 对象上定义 require
和 define
方法并隐藏模块进入这样的匿名范围:
(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)
这样,define
和 require
是唯一可以让您访问模块的函数。如果不首先要求其他模块,其他模块将无法修改其他模块。这在使用可能与您的模块系统冲突的第三方脚本时很有用。