这是逐行解释(带有标题只是为了将其分解):
设置:
// Create an anonymous function expression taking `NAMESPACE` as a parameter.
// Likely the *real* namespace will be passed to the function at the end
// with ... })(realnamespacetomodify);
(function(NAMESPACE) {
// Create the new part of the namespace. Note that we are editing a reference
// so really this change happens on whatever object was passed in.
NAMESPACE.nav = {};
// Create a local pointing to this new sub-namespace. Probably just for
// convenience, also possibly for portability (if the name is used in closures,
// then those closures don't need to refer to NAMESPACE directly).
var nav = NAMESPACE.nav,
模块定义:
// While nav refers to an object likely in global scope, nav itself can
// never be referred to from global scope because it is a local here.
// These variables are local here. They can never be referred to by global scope.
_isNavOpen = false,
_inner = document.getElementById('inner-wrap');
// These variables, added to nav, can be accessed using the object that
// nav refers to in global scope (see the end).
nav.CLASS = 'js-nav-open';
...
// This function is also added to nav, therefore it can be accessed outside
nav.toggle = function(event) {
...
// This reference to _isNavOpen resolves because this function
// is a closure, and binds variables outside its scope
// to the function itself. So even though _isNavOpen can't be
// accessed globally, it can be accessed here, making it like
// a private member of this namespace.
if(_isNavOpen && $('html').hasClass(nav.CLASS)) {
// nav is also bound by the closure and can be accessed here
nav.close();
} ...
};
在全局空间中使用:
}(PROJECT_NAME));
console.log(PROJECT_NAME.nav.CLASS); // "js-nav-open"
console.log(PROJECT_NAME.nav.toggle); // Function object
这是一个模块模式。使用它有几个原因:
- 代码可移植性(不指模块内的全局对象)
- 作用域(避免将不必要的变量分配给全局命名空间)
- 可见性(隐藏私有访问变量)
至于前三行本身(您的原始问题),他们可以直接引用PROJECT_NAME
,但看起来它已被设置为帮助代码可移植性。您会注意到匿名函数本身从不指向真实对象 ( PROJECT_NAME
)。这意味着您可以复制和粘贴此部分,并且只能在一个地方更改该引用。
另一个答案提到了范围,虽然这也很重要,但它并没有解释这段代码的所有好处,例如为什么它不直接引用现有的全局变量。使用模式的这一部分可以实现范围隐藏的好处:
(function() {
... // Anything set here is local, not global.
})();