我有以下代码定义Car
。每个Car
都有一个颜色,还有一个setColor(color)
函数。我想添加在调用setColor(color)
时调用的侦听器函数,并且我希望能够随时随地处理这些侦听器函数。这是一种合适的方法吗?有更清洁的方式吗?
function Car() {
this._color = 'red';
this._callbacks = {};
this.setColor = function(color) {
this._color = color;
console.log(">>> set car color to " + color);
if (this._callbacks['setColor']) {
this._callbacks['setColor']();
}
};
this.addListener = function(functionName, handler) {
if (this._callbacks[functionName]) {
var oldCallback = this._callbacks[functionName];
this._callbacks[functionName] = function() {
oldCallback();
handler();
}
} else {
this._callbacks[functionName] = function() {
handler();
}
}
};
}
var car = new Car();
car.setColor('blue');
car.addListener('setColor', function() { console.log("This is listener # 1"); });
car.setColor('green');
car.addListener('setColor', function() { console.log("This is listener # 2"); });
car.setColor('orange');
输出:
>>> setColor to blue
>>> setColor to green
This is listener # 1
>>> setColor to orange
This is listener # 1
This is listener # 2
答案 0 :(得分:3)
我认为存储侦听器的数组将是一种更清晰的方法。此外,您应该使用原型对象,或使半私有属性成为真正的私有变量。
function Car() {
this._color = 'red';
this._callbacks = {setColor:[]};
};
Car.prototype.setColor = function(color) {
this._color = color;
console.log(">>> set car color to " + color);
for (var i=0; i<this._callbacks['setColor'].length; i++)
this._callbacks['setColor'][i]();
};
Car.prototype.addListener = function(functionName, handler) {
this._callbacks[functionName].push(handler);
};
或者:
function Car() {
var color = 'red';
var callbacks = {};
this.setColor = function(c) {
color = c;
console.log(">>> set car color to " + color);
for (var i=0; 'setColor' in callbacks && i<callbacks['setColor'].length; i++)
callbacks['setColor'][i]();
};
this.addListener = function(functionName, handler) {
if (functionName in callbacks)
callbacks[functionName].push(handler);
else
callbacks[functionName] = [handler];
};
}
答案 1 :(得分:2)
也许这样的事情。
//the 'class'
function Car() {
//set up a static listeners object - an array for each method
Car.listeners = {setColor: []};
//called by methods on invocation, to fire their listeners
Car.executeListeners = function(methodName) {
for (var i=0, len = Car.listeners[methodName].length; i<len; i++)
Car.listeners[methodName][i].apply(this);
};
//method - on invocation, fire any listeners
this.setColor = function(color) {
this.color = color;
Car.executeListeners.call(this, 'setColor');
};
}
//instance
var car = new Car();
//add a listener to instance.setColor invocations
Car.listeners.setColor.push(function() {
alert("hello - this car's color is "+this.color);
});
//set color (triggers listener)
car.setColor('orange');
请注意,您将prototype-esq方法分配给实例而不是原型本身 - 继承可重用功能的位置。性能方面的继承也更快。
答案 2 :(得分:1)
如果它适合你,那么我认为没有理由不去使用它。关于这种方法的一些想法:
addListener
方法获取上下文对象并执行callback.call(context)
。如果你不关心这个,那就不用担心了。callback(this, this._color)
?要考虑的另一件事是使用Object.defineProperty
,但这是一种更具风格的选择。