繁体   English   中英

是否可以在构造函数之外定义特权方法?

[英]Is it possible to define priviledge method outside of the constructor?

好吧,我有一个带有一个秘密和一个方法的构造函数:

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"

那么有可能在构造函数之外定义特权方法吗? 怎么样?

可以用eval完成吗? (我知道...这很邪恶...我只是有兴趣)

在javascript中进行范围界定的基本想法是,这不应该实现,我建议在构造函数的范围内添加一个函数getPrivate ,并使用该函数来访问“私有”变量。

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"]; 
    }
}

是的,可以在构造函数之外定义特权方法。 这是操作方法:

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;
}({}));

下面是它的工作原理:

  1. 我们通过创建立即调用函数表达式(IIFE)来创建名称空间。
  2. 我们创建一个称为key的对象。 该对象是我们刚创建的名称空间的私有对象。 因此,只有特权函数和构造函数才能访问它。
  3. 在构造函数内部,我们创建了一个名为private的对象,该对象保存每个实例的私有状态。
  4. 我们还创建了一个名为getPrivate的特权方法,该方法带有参数k并且如果k是我们在步骤2中创建的key ,则仅返回私有对象。因此,只有特权函数才能访问私有对象。
  5. 想要访问对象的私有状态的特权函数必须调用getPrivate(key)以获得私有状态对象。

注意:仅当您具有多个需要访问对象的私有状态的特权函数时,此方法才有用。 另外, getPrivate调用对特权函数造成了非常小的性能开销。


顺便说一句,如果您想用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;
    }
}, {});

我永远不会这样做,但这是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; 
};

实时示例http://jsfiddle.net/claustrofob/yu6VJ/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM