【发布时间】:2013-10-12 10:48:07
【问题描述】:
到目前为止,我主要从事 Java 项目,并试图了解 Javascript 和模块化。我真的很喜欢 Java 中经常使用的观察者模式,因此我实现了一个 Pub/Sub 模块,它可以用来监听模型模块的变化。
这是我的测试应用程序的组件。
TestModel.js
define("testModel", ["observable"],
function (observable) {
var TestModel = (function () {
function TestModel() {
this.name = "name";
}
TestModel.prototype.setName = function (name) {
this.name = name;
this.publish(name);
};
observable.makeObservable(TestModel.prototype);
return TestModel;
})();
return {
TestModel: TestModel
};
});
TestView.js
define("testView", [],
function () {
var TestView = (function () {
function TestView() {
this.string = "my Name is ";
}
TestView.prototype.talk = function (test, self) {
console.log(self.string + test);
//HERE this.string IS UNDEFINED !!!!, because TestModel called talk()
console.log(this.string + test);
}
return TestView;
})();
return {
TestView: TestView
};
});
testapp.js
define("testapp", ["testModel", "testView"], function (testModel, testView) {
var initialize = function () {
var model = new testModel.TestModel();
var view = new testView.TestView();
model.addSubscriber(view.talk, view);
model.setName("Frank");
}
return {
initialize: initialize
};
});
而 observable 模块只是通过调用向模型添加了 3 个通用函数
makeObservable()
observable.js
define("observable", [],
function () {
/**
* Observable Object, holds 3 geneneric functions.
* @type {{addSubscriber: Function, removeSubscriber: Function, publish: Function}}
*/
var Observable = {
addSubscriber: function (callback, subscriber) {
this.callbacks[this.callbacks.length] = callback;
this.subscribers[this.subscribers.length] = subscriber;
},
removeSubscriber: function (callback) {
for (var i = 0; i < this.callbacks.length; i++) {
if (this.callbacks[i] === callback) {
delete(this.callbacks[i]);
delete(this.subscribers[i]);
}
}
},
publish: function (what) {
for (var i = 0; i < this.callbacks.length; i++) {
if (typeof this.callbacks[i] === 'function') {
this.callbacks[i](what, this.subscribers[i]);
}
}
}
}
/**
* Function takes another function Module and adds the 3
* functions from Observable to it.
*
* @param o
*/
var makeObservable = function (o) {
// turns an object into a publisher
for (var i in Observable) {
o[i] = Observable[i];
o.callbacks = [];
o.subscribers = [];
}
}
return {
makeObservable: makeObservable
};
});
现在我的问题。我真的不想在模型中保存订阅者列表,这在某种程度上违反了松散耦合的原则。但是如果我只在subscribe()方法中给TestModel添加一个回调函数,我将无法访问TestView中的this.string变量。因为this 指向调用了talk() 方法的TestModel。我的解决方法是 self,这导致模型中需要订阅者列表。
我还尝试在 RequireJS 调用和返回的 TestView 函数中初始化 TestView 函数之外的 self 变量。但是这个函数只被调用一次,因此该变量在 Java 中就像一个静态变量,并且在 TestView 的每个实例中都不是唯一的。
是否有可能在talk() 函数中获得一个self/this 变量来访问字符串,而无需像现在这样由TestModel 处理它?
【问题讨论】:
-
使用
model.addSubscriber(view.talk.bind(view))然后回调将隐式地将视图绑定到回调的this引用。否则,您可以执行model.addSubscriber(view, "talk")之类的操作并让Observable调用this.subscribers[i][this.methodNames[i]].call(this.subscribers[i], what)。 -
model.addSubscriber(view.talk.bind(view)) 似乎正是我想要的。非常感谢你。是否有可能支持您的评论?将鼠标悬停在它上面时应该会出现一个箭头,但我看不到一个。
-
好的,我会添加作为答案,也许问题可以这样结束。
标签: javascript requirejs this publish-subscribe