提问人:Psyfun 提问时间:7/2/2022 最后编辑:Psyfun 更新时间:7/6/2022 访问量:115
JavaScript 嵌套命名空间和状态变量
JavaScript nested namespaces and state variables
问:
我正在尝试使用带有匿名函数和闭包的模块模式实现嵌套命名空间。当涉及到状态变量的变化时,我错过了一些东西。例如,下面是一组简单的嵌套命名空间:
// namespace 1
var first = (function(){
'use strict';
var v = 1;
function method(){
console.log("method 1: " + v);
}
// namespace 2
var second = (function(){
var v = 2;
function method(){
console.log("method 2: " + v);
}
// namespace 3
var third = (function(){
var v = 3;
function method(){
console.log("method 3: " + v);
}
return {
v: v,
method: method
};
})();
return {
third: third,
v: v,
method: method
};
})();
return {
second: second,
v: v,
method: method
};
})();
first.method();
first.v = 4;
first.method();
first.second.method();
first.second.third.method();
这将导致以下输出:
"method 1: 1"
"method 1: 1"
"method 2: 2"
"method 3: 3"
为什么改变不坚持下去?first.v
更新:所以,我现在明白了为什么这不能根据反馈。我现在已经切换到使用对象文字。我仍在努力寻找嵌套命名空间和范围的最佳方法。这是我上面代码的新版本:
var first = {
v: 1,
method: function (){
console.log("method 1: " + this.v);
},
second: {
v: 2,
method: function (){
console.log("method 2: " + this.v);
},
third: {
v: 3,
method: function (){
console.log("method 3: " + this.v);
}
}
}
}
first.method();
first.v = 4;
first.method();
first.second.method();
first.second.third.method();
更新2:因此,在查看不同的资源时,我再次更新了我的方法。这是我首先尝试走的路线,但我一直收到一个奇怪的错误,即函数不是函数。这是我使用相同示例的更新版本:
var first = window.first || {};
first.second = first.second || {};
first.second.third = first.second.third || {};
first.v = 1;
first.method = function (data) {
console.log("method 1: " + this.v);
};
first.second.v = 2;
first.second.method = function (data) {
console.log("method 2: " + this.v);
}
first.second.third.v = 3;
first.second.third.method = function (data) {
console.log("method 3: " + this.v);
}
first.method();
first.v = 4;
first.method();
first.second.method();
first.second.third.method();
现在我只想确保我有正确的范围。使用 时,它应该引用当前对象的作用域而不是全局,对吗?this
答:
-1赞
Scott Marcus
7/2/2022
#1
命名空间不是由嵌套函数创建的。它们是通过在现有对象上创建新属性,然后将新成员附加到这些属性来创建的:
(function(){
// Just create members of the instance as normal
// No nesting here. Within a function variables are
// private, but "this" properties are available
// and can persist state.
this.foo = function(){console.log("foo"); };
this.bar = function(){console.log("bar")};
this.baz = function(){console.log("baz")};
this.x = 42;
// We can't change the state of the above variable directly
// but we can create a function that works with that value
// and modifies it.
this.changeX = function(n){
this.x += n;
};
// If we create a new property on the Global object
// that is an empty object, we'll be essentially
// creating a namespace to be accessed from the Global object
window.namespace = {};
// Then, create new properties on that object, which point
// to state or behavior that you want to expose in the namespace
window.namespace.foo = foo;
window.namespace.bar = bar;
window.namespace.x = x;
window.namespace.changeX = changeX;
// And to create nested namespaces, repeat by adding a new empty
// object as a new property of the current namespace.
window.namespace.ns2 = {};
// And then associate internal state or behavior with that namespace
window.namespace.ns2.baz = baz;
})();
// Since our namespace is attached to the Global object (window),
// we don't have to fully qualify it with window and can just
// access the namespace directly.
namespace.foo();
namespace.bar();
namespace.ns2.baz();
console.log(namespace.x); // 42
namespace.changeX(-10);
console.log(namespace.x); // 32
评论
0赞
Bergi
7/2/2022
IIFE 不是一个实例。在严格模式下,将未定义。this
0赞
Scott Marcus
7/2/2022
@Bergi 谢谢。更正了措辞。我知道这不是一个实例。我试图传达使用(不是在严格模式下,因为从未提到过)将区分局部变量和暴露的成员。this
0赞
Bergi
7/2/2022
你是想鼓励在这里使用草率模式吗? 在IIFE中不是指“暴露的成员”,而是指全局对象的成员,应绝对避免。this
评论
new