我有这个构造函数有一个秘密和一个方法:
function Keeper(get) {
var secretPower = 'wisdom';
this.get = get ? get : function () {
return 'Its secret power is: ' + secretPower;
}
// now this is privileged method only in case that there are no arguments?
}
现在我将制作两个实例,一个具有特权方法......
var yourKeeper = new Keeper();
yourKeeper.get(); // "Its secret power is: wisdom"
......但另一个是不同的。它可以触及它周围的上下文,但不能触及构造函数的私有......
var myKeeper = new Keeper(function() {
return 'Its secret power is: ' + secretPower;
});
myKeeper.get(); // ReferenceError: secretPower is not defined
...这也不是我想要的:
myKeeper.get = function() {
return 'Its secret power is: ' + secretPower;
}
myKeeper.get(); // ReferenceError: secretPower is not defined
当然它不起作用,因为secretPower
在这些情况下是全局变量,所以:
var secretPower = 'none';
myKeeper.get(); // "Its secret power is: none"
那么是否可以在构造函数之外定义priviledge方法?如何?
可以用eval完成吗?(我知道......这很邪恶......我只是感兴趣)
答案 0 :(得分:2)
javascript中的作用域背后的想法是,这应该是不可能的,我建议在构造函数的范围内添加函数getPrivate
并使用它来访问“私有”变量。 / p>
function Keeper(get) {
var semiPrivates = {
secretPower:'Wisdom'
}
this.getPrivate = function (variable){
return semiPrivates[variable];
}
this.get = get ? get : function () {
return 'Its secret power is: ' + semiPrivates["secretPower"];
}
}
答案 1 :(得分:2)
是的,可以在构造函数之外定义特权方法。以下是如何做到这一点:
var Keeper = (function (key) {
function Keeper(get) {
var private = {
secretPower: "wisdom"
};
this.getPrivate = function (k) {
if (k === key) return private;
};
this.get = get || defaultGet;
}
function defaultGet() {
var private = this.getPrivate(key);
return "The secret power is: " + private.secretPower;
}
return Keeper;
}({}));
以下是它的工作原理:
key
的对象。此对象是我们刚刚创建的命名空间的私有对象。因此,只有特权函数和构造函数才能访问它。private
的对象,它保存每个实例的私有状态。getPrivate
的特权方法,该方法接受参数k
,并且只有k
是我们在步骤2中创建的key
时才返回私有对象。因此只有特权函数才能访问私有对象。getPrivate(key)
来获取私有状态对象。 注意:此方法仅在您有多个特权函数需要访问对象的私有状态时才有用。此外,调用getPrivate
会给特权函数带来(非常)小的性能开销。
BTW如果你想在JavaScript中编写干净的面向对象代码,那么看一下augment
库。上面的代码使用augment
:
var Keeper = Object.augment(function (key) {
this.constructor = function (get) {
var private = {
secretPower: "wisdom"
};
this.getPrivate = function (k) {
if (k === key) return private;
};
this.get = get || defaultGet;
};
function defaultGet() {
var private = this.getPrivate(key);
return "The secret power is: " + private.secretPower;
}
}, {});
答案 2 :(得分:1)
我永远不会这样做,但这是一个eval
的解决方案:
function test(){
var private = 'hello';
this.say = function(){
}
this.setSay = function(func){
eval('this.say = ' + func.toString());
}
}
var x = new test();
x.setSay(function(){
console.log(private + ' world');
});
x.say();
示例http://jsfiddle.net/claustrofob/AwMd3/
以下是与Keeper
对象相关的示例:
function Keeper(get) {
var secretPower = 'wisdom';
var getFunc = function () {
return 'Its secret power is: ' + secretPower;
};
var evalFunc = function(variable, val){
eval(variable + ' = ' + val.toString());
};
this.__defineSetter__("get", function(val){
evalFunc('getFunc', val);
});
this.__defineGetter__("get", function(val){
return getFunc;
});
if (get !== undefined){
evalFunc('getFunc', get);
}
}
这里我们为您的get
方法定义setter和getter,这样您就可以通过这种方式初始化对象:
var x = new Keeper(function () {
return 'Its secret power is: ' + secretPower;
});
这样:
var x = new Keeper();
x.get = function () {
return 'Its secret power is: ' + secretPower;
};