JavaScript 模块模式变量范围
javascript module pattern variable scope
我正在学习javascript和模块模式,但我在代码中犯了一个错误,事实证明它对这种模式的一些概念是正确的。我的基本代码是这样的:
(function(window,$){
//global menu object
var menu = (function(){
//menu tab component
var tab = (function(){
//public properties
var tab = {
init:doStuff
}
//private properties
function doStuff(){
alert("initialising Tab")
}
//return public properties
return tab;
})();
//menu curtain component
var curtain = (function(){
//public properties
var curtain = {
init:doStuff
}
//private properties
function doStuff(){
alert("initialising Curtain")
}
//return public properties
return curtain;
})();
//menu content component
var content = (function(){
//public properties
var content = {
init:doStuff
}
//private properties
function doStuff(){
alert("initialising Content")
}
//return public properties
return content;
})();
//public properties
var menu = {
init:initialiseMenu
}
//private properties
function initialiseMenu(){
//initialise each component of the menu system
tab.init();
curtain.init();
content.init();
}
//final menu object
return menu;
})();
window.menu = menu;
})(window,jQuery);
然后,当我的页面加载并调用代码时:
menu.init();
它按顺序发出警报:
initialising tab
initialising curtain
initialising content
正如我所料。但是如果我将内容组件更改为如下所示:
//menu content component
var content = (function(){
//public properties
var content = {
init:doStuff
}
//private properties
function doStuff(){
alert("initialising Content")
}
//CHECK ACCESS TO PREVIOUS VARIABLES
curtain.init();
//return public properties
return content;
})();
它按顺序发出警报:
initialising curtain
initialising tab
initialising curtain
initialising content
所以我看到它能够访问 curtain 变量,即使它没有作为参数传递到模块中。我以为每个模块都是自包含的,但我发现事实并非如此,无论如何可以让模块也只能访问您想要的变量吗?特别是对我的例子会有所帮助,谢谢丹。
每个模块都不是自包含的,而是创建一个新作用域,该作用域是创建该模块的超集。在 Javascript 中定义新作用域的唯一内容是 function
语句。在新作用域中,外部作用域中的所有内容都是可见的,除非被同名的变量覆盖。内部范围内的任何内容都对它之外的东西是可见的。
var global;
function outer() {
var outerVar;
function inner() {
var innerVar;
// global, outerVar, and innerVar are visible
}
function inner2() {
var inner2var, outerVar;
// global and inner2var are visible
// outerVar hides the previous outerVar, which is no longer accessible
}
// global and outerVar (the first one) are visible
}
您的函数是自执行的事实并没有区别。在外部作用域中创建的任何内容都将在内部作用域中可见,除非您创建一个同名的新局部变量来取代它。
就您的内部范围而言,在其外部创建的任何内容都与全局范围大致相同。(全局只是在默认范围内创建的变量,即浏览器中的"窗口")。
你可以把一个内在的范围想象成在单向玻璃后面。你仍然可以看到世界上的一切,但世界看不到你。而且你总是可以选择挡住单向玻璃,这样你就再也看不见外面了。但没有什么能看到里面。
任何函数的当前作用域都可以看到它的包含作用域。 因此,内容仍然可以访问菜单中的任何变量,其中包括窗帘。
发生这种情况是因为当您在每个对象中调用"return"时,您将返回值分配给组件变量,该值是每个组件中的内部"公共属性"对象。
var tab = (function(){
//public properties
var tab = {
init:doStuff
}
//private properties
function doStuff(){
alert("initialising Tab")
}
//return public properties
return tab;
})();
在这里,您将原始变量"tab"与正在执行的匿名函数的结果一起分配。本例中的对象是:
var tab = {
init:doStuff
}
因为您在函数执行结束时返回此对象。
若要实现所追求的目标,请尝试返回一个具有"public"修饰符函数的对象,该修饰符函数访问函数范围内的变量。在函数中创建的任何变量都只具有该函数或其作用域内的函数的作用域,从而使它们有效地私有(Javascript 在功能上是作用域的)。以下示例应该可以帮助您处理代码:
var tab = (function(){
//public properties
var PublicProperties = {
init:doStuff,
modifyPrivateVar: function(value){
this.somePrivateVariable = value;
}
}
//private variables/properties
var doStuff = function(){
alert("initialising Tab")
}
var somePrivateVariable = 'private!';
//return public properties
return PublicProperties;
})();
现在,您的变量"tab"将通过执行匿名函数为返回的值(PublicProperties 对象)分配。你可以访问函数"init"和"modifyPrivateVar",但你不能直接调用"doStuff"或更改"somePrivateVariable"。这表明您可以通过修饰符函数更改变量,但不能直接访问它,从而使它有效地私有。
如果您希望将"init"函数作为构造函数调用,则必须在组件的匿名函数执行中执行"构造函数",或者只是内联编写代码,它将在组件的匿名函数执行时执行。否则,如果 init 函数是私有的,则不应返回与该函数相关的任何内容,而只返回可用于以安全方式修改/激活对象的函数。
- ngDialog-弹出窗口未更新范围变量
- AngularJS范围变量Unwatch
- 将外部控制器的范围变量设置为角度
- 对于使用传递的数据计算的局部范围变量,角度绑定在自定义指令中不起作用
- 如何使用EnquireJS使AngularJS范围变量依赖于媒体查询
- 具有范围变量的控制器不工作
- 范围变量返回长度错误
- 将 NodeJS 模块范围变量作为对象访问
- Angularjs 更新 setTimeout 中的范围变量不起作用
- 递归承诺调用 - 内存范围变量问题
- AngularJS:从指令设置范围变量
- Angularjs:访问范围变量数组并计算平均值
- 范围变量更新,但不更新视图
- 从html调用angularjs控制器中的一个函数,但未定义范围变量
- 如何在编辑范围变量时(暂时)避免摘要循环
- 防止Angular范围变量通过引用自动绑定到服务私有成员
- 使用 AngularJS 从指令设置范围变量
- 集合回调忽略范围变量
- 使用forEach修改角度范围变量
- 因果报应测试中未定义的预期范围变量