Если вы хотите, чтобы instanceof
работал, нам нужно использовать наследование, например, решение @ nrabinowitz.В этом решении нежелательные методы скрываются с ключами, установленными в нуль, и эти ключи доступны пользователю, поэтому они могут быть сброшены пользователем.Мы можем предотвратить это, скрыв эти ключи в промежуточном объекте, и поскольку он создается из промежуточного класса, чтобы наследование не нарушалось.
function restrict(original, whitelist) {
/* create intermediate class and instantiate */
var intermediateClass = function() {};
intermediateClass.prototype = original;
var intermediateObject = new intermediateClass();
/* create restricted class and fix constructor reference after prototype replacement */
var restrictedClass = function() {};
restrictedClass.prototype = intermediateObject;
restrictedClass.prototype.constructor = original.constructor;
if (restrictedClass.prototype.constructor == Object.prototype.constructor) {
restrictedClass.prototype.constructor = restrictedClass;
}
for (var key in original) {
var found = false;
for (var i = 0; i < whitelist.length; i++) {
if (key == whitelist[i]) {
if (original[key] instanceof Function) {
/* bind intermediate method to original method */
(function(key) {
intermediateObject[key] = function() {
return original[key].apply(original, arguments);
}
})(key);
}
found = true;
break;
}
}
if (!found) {
/* black out key not in the whitelist */
intermediateObject[key] = undefined;
}
}
return new restrictedClass();
}
В следующем примере i
и j
представляютдва способа реализации значений членов.Один из них является закрытым членом в закрытии, а другой - открытым членом класса.
var originalClass = function() {
var i = 0;
this.j = 0;
this.getI = function() {
return i;
};
this.setI = function(val) {
i = val;
};
}
originalClass.prototype.increaseI = function() {
this.setI(this.getI() + 1);
};
originalClass.prototype.decreaseI = function() {
this.setI(this.getI() - 1);
};
originalClass.prototype.getJ = function() {
return this.j;
};
originalClass.prototype.setJ = function(val) {
this.j = val;
};
originalClass.prototype.increaseJ = function() {
this.setJ(this.getJ() + 1);
};
originalClass.prototype.decreaseJ = function() {
this.setJ(this.getJ() - 1);
};
var originalObject = new originalClass();
var restrictedObject = restrict(originalObject, ["getI", "increaseI", "getJ", "increaseJ"]);
restrictedObject.increaseI();
restrictedObject.increaseJ();
console.log(originalObject.getI()); // 1
console.log(originalObject.getJ()); // 1
console.log(restrictedObject instanceof originalClass); // true
Как видите, все методы установки и уменьшения скрыты в ограниченном объекте.Пользователь может использовать только геттер или увеличить значение i
и j
.