在JavaScript中,是否可以在影响其所有兄弟姐妹的对象上调用实例方法?
例如,假设我有以下课程:
function Thing() {
this.active = false;
}
Thing.prototype = {
constructor: Thing,
activate: function() {
this.active = true;
},
deactivate: function() {
this.active = false;
}
};

我是否可以创建一个可以激活类activateAll
的所有实例的Thing
方法?
我需要this.active
成为实例变量。
答案 0 :(得分:7)
您可以将所有实例存储在数组中,并迭代它们以更改其active
属性。但是,存储所有实例意味着它们不会被垃圾回收,因此您将浪费内存。如果阵列变得庞大,那么迭代就会很慢。
var Thing = (function() { // Use a closure to hide `instances`
var instances = [];
function Thing() {
this.active = false;
instances.push(this);
}
Thing.prototype.activate = function() {
this.active = true;
};
Thing.prototype.activateAll = function() {
instances.forEach(function(instance) {
instance.active = true;
});
};
return Thing;
})();
更好的方法是为每个实例定义公共默认活动和默认优先级,以及自己的活动和自己的优先级。然后,
var Thing = (function() {
var defActive = false, /* default activity */
defPriority = 0; /* default priority */
/* `defPriority >= ownPriority` will always hold */
function Thing() {
var ownActive,
ownPriority = -1;
Object.defineProperty(this, 'active', {
get: function() {
return defPriority > ownPriority ? defActive : ownActive;
},
set: function(val) {
ownActive = val;
ownPriority = defPriority;
}
});
}
Thing.prototype.activate = function() {
this.active = true;
};
Thing.prototype.activateAll = function() {
defActive = true;
++defPriority;
};
return Thing;
})();
如果多次调用activateAll
并且您不想不必要地增加defPriority
,则可以添加一个布尔变量来了解某些属性是否达到默认属性。
var Thing = (function() {
var defActive = false, /* default activity */
defPriority = 0, /* default priority */
someOwnPriorityReachedDefPriority = false;
function Thing() {
var ownActive,
ownPriority = -1;
Object.defineProperty(this, 'active', {
get: function() {
return defPriority > ownPriority ? defActive : ownActive;
},
set: function(val) {
ownActive = val;
ownPriority = defPriority;
someOwnPriorityReachedDefPriority = true;
}
});
}
Thing.prototype.activate = function() {
this.active = true;
};
Thing.prototype.activateAll = function() {
defActive = true;
if(someOwnPriorityReachedDefPriority) {
++defPriority;
someOwnPriorityReachedDefPriority = false;
}
};
return Thing;
})();
在任何情况下,请注意在原型中添加该方法没有多大意义。根据OOP原则,在变量中调用方法不应影响其他变量。相反,请考虑将该方法添加到构造函数本身。
一个完整的例子可能是这样的:
var Thing = (function() {
var defActive = false, /* default activity */
defPriority = 0, /* default priority */
someOwnPriorityReachedDefPriority = false;
function Thing() {
var ownActive,
ownPriority = -1;
Object.defineProperty(this, 'active', {
get: function() {
return defPriority > ownPriority ? defActive : ownActive;
},
set: function(val) {
ownActive = val;
ownPriority = defPriority;
someOwnPriorityReachedDefPriority = true;
}
});
}
Thing.prototype.activate = function() {
this.active = true;
};
Thing.prototype.deactivate = function() {
this.active = false;
};
Object.defineProperty(Thing, 'activeAll', {
set: function(val) {
defActive = val;
if(someOwnPriorityReachedDefPriority) {
++defPriority;
someOwnPriorityReachedDefPriority = false;
}
}
});
Thing.activateAll = function() {
Thing.activeAll = true;
};
Thing.deactivateAll = function() {
Thing.activeAll = false;
};
return Thing;
})();
答案 1 :(得分:1)
你需要一个instances
数组,如下所示:
var instances = [];
修改Thing
,如下所示:
function Thing() {
this.active = false;
instances[instances.length] = this;
}
通过迭代实现方法:
function activateAll() {
for (var index in instances) {
instances[index].active = true;
}
}
您可以概括一下,如下所示:
function genericOperation(f, p) {
for (var index in instances) {
instances[index].f(p);
}
}