我花了大部分时间阅读有关模块模式及其“此”范围的内容。最终我找到了解决问题的方法,尽管有一种更好的做事方式。
实际代码大于200行,但我将其归结为以下内容: objA有一个objB希望通过回调调用的方法(publicA)。使事情变得复杂的细节是publicA需要来自publicA_helper的帮助来完成它的工作。 (http://jsfiddle.net/qwNb6/2/)
var objA = function () {
var privateA = "found";
return {
publicA: function () {
console.log("privateA is " + this.publicA_helper());
},
publicA_helper: function () {
return privateA;
}
};
}();
var objB = function () {
return {
callback: function (callback) {
callback();
}
}
}();
objA.publicA(); // privateA is found
objB.callback(objA.publicA); // TypeError: Object [object global]
足够公平 - 我已经意识到调用者的上下文会影响'this'的值。所以我添加了一些措施来保留objA中的'this',其中似乎没有效果。我试过了
var objA = (){}.call({})
,设置var self = this;
(相应地调用self.publicA_helper()
)。没有运气。
最后,我添加了一个私有变量var self;
以及一个公共方法:
init: function() {self = this;},
...并确保在将objA.init();
传递给objA.publicA
之前致电objB.callback
,事情确实有效。
我无法强调这种感觉有一种更好的方式。我错过了什么?
答案 0 :(得分:3)
通用解决方案非常简单。
将所有模块的方法写为私有,然后公开那些需要公开的方法。
我用这种方式编写所有模块:
var objA = function () {
var privateA = "found";
var A = function () {
console.log("privateA is " + A_helper());
},
var A_helper = function () {
return privateA;
}
return {
publicA: A
//A_helper need not be exposed
};
}();
因此,所有方法都在相同的范围内,每个方法都可以直接访问同一模块中的所有其他方法,并且避免使用模糊的this
前缀。
objB.callback(objA.publicA);
现在可以按预期工作了。
参见 fiddle
答案 1 :(得分:1)
我尝试了
var objA = (){}.call({})
的东西,
如何?您希望在要使用自定义call
调用的回调上使用this
,而不是在模块闭包上。它应该是
var objB = {
callback: function (callback, context) {
callback.call(context);
}
};
objB.callback(objA.publicA, objA);
我尝试过设置
var self = this;
self
变量应该在闭包中并指向存储方法的对象。当您的模块上调用模块IEFE时,这只是this
- 事实并非如此。或者,如果它是一个构造函数 - 它不是。您可以使用call
进行更改,如上所述:
var objA = function () {
var privateA = "found",
self = this;
this.publicA = function () {
console.log("privateA is " + self.publicA_helper());
};
this.publicA_helper = function () {
return privateA;
};
return this;
}.call({});
但那很难看。在您的情况下,自变量只需要指向您作为模块返回的对象文字:
var objA = function () {
var privateA = "found",
self;
return self = {
publicA: function () {
console.log("privateA is " + self.publicA_helper());
},
publicA_helper: function () {
return privateA;
}
};
}();
顺便说一句,既然你正在创建一个单例,你不需要一个明确的self
,你可以只引用包含你的模块的变量(只要它不会改变):
var objA = function () {
var privateA = "found";
return {
publicA: function () {
console.log("privateA is " + objA.publicA_helper());
},
publicA_helper: function () {
return privateA;
}
};
}();
另一种方法是简单地将所有函数设为私有,然后公开其中的一些 - 通过引用它们本地范围,你将没有麻烦。
var objA = function () {
var privateA = "found";
function publicA() {
console.log("privateA is " + helper());
}
function helper() {
return privateA;
}
return self = {
publicA: publicA,
publicA_helper: helper // remove that line if you don't need to expose it
};
}();
答案 2 :(得分:0)
原因是在调用回调时上下文会发生变化。不是通用的解决方案,但通过在调用回调时指定上下文来显示代码的工作原理。
var objA = function () {
var privateA = "found";
return {
publicA: function () {
console.log("privateA is " + this.publicA_helper());
},
publicA_helper: function () {
return privateA;
}
};
}();
var objB = function () {
return {
callback: function (callback) {
callback.call(objA);
}
}
}();
objA.publicA(); // privateA is found
objB.callback(objA.publicA); // privateA is found