make object子原型具有父对象的上下文

时间:2014-09-25 20:36:59

标签: javascript oop prototype

这可能是重复的,如果是的话,我道歉。我已经查看了几个问题,并且没有找到一个与我的情况完全匹配的问题(这可能是一个不好的开头)。

我有一个班级,比如RandomClass,定义如下

function RandomClass(id){
    this._id = id;
}

RandomClass.prototype.getID = function(){
    return this._id;
}

var rc = new RandomClass(1);
rc.getID(); //returns 1, as expected

假设我想定义一组处理程序,并将它们保存在RandomClass的子对象(继续使用原型)中。 我对原型的了解有些限制,所以如果下一步是非常糟糕的形式,请道歉。

RandomClass.prototype.handlers = {};

RandomClass.prototype.handlers.HandlerOne = function(){
   console.log("Handler one calling from ID: "+this._id); 
   //the context is not the context of RandomClass, but of RandomClass.prototype.handlers!
}

rc.handlers.HandlerOne(); //prints "Handler one calling from ID: unknown"

同样,也许这是一个糟糕的形式,但是我有几个需要调用的处理程序,这样做可以简化代码:

var handler = "one of many many handlers returned from an ajax request";
rc.handlers[handler]();

所以,我的问题是如何让HandlerOne的上下文成为RandomClass的上下文而不是处理程序?我想继续使用原型,因为那样的话不会多次克隆(如下例所示):

function RandomClass(id){
    this._id = id;
    this._handlers = {};
}

function HandlerOne(){
    console.log("Handler one calling from ID: "+this._id);
}

var rc = new RandomClass(1);
rc._handlers["HandlerOne"] = HandlerOne.bind(rc);
rc._handlers["HandlerOne"]() //prints as expected, but I believe performance is much worse here

3 个答案:

答案 0 :(得分:1)

可以满足你这样做,而不是绑定上下文尝试将其作为参数传递。

function RandomClass(id){
    this._id = id;
    this._handlers = {};
}

function HandlerOne(instance){
    var parentScope = instance;

    console.log("Handler one calling from ID: "+parentScope._id);
}

//call it like this
var rc = new RandomClass(1);
rc._handlers["HandlerOne"] = HandlerOne;
rc._handlers["HandlerOne"](rc)

答案 1 :(得分:1)

您可以简单地将Handlers设为自己的。请注意,您不应该像我在下面的示例中那样访问之外的私有成员。您必须公开正确的公共API,以使对象协同工作而不会违反封装。

function RandomClass(id){
    this._id = id;
    this.handlers = new Handlers(this);
}


function Handlers(randomClassInstance) {
    this._randomClassInstance = randomClassInstance;
}

Handlers.prototype = {
    constructor: Handlers,

    handlerOne: function () {
        console.log("Handler one calling from ID: "+ this._randomClassInstance._id);
    }
};

然后你可以这样做:

var rnd = new RandomClass('test');

rnd.handlers.handlerOne(); //Handler one calling from ID: test

答案 2 :(得分:0)

此时提交的两个答案都是很好的替代方案(我认为是可以接受的),但是我已经决定采用另一种方式(这导致对我的代码进行最少量的修改:)。

与@ BlaShadow的答案类似,我只是使用Javascript的parentScope方法传递正确的上下文,而不是传递上下文并设置function.call()变量。

function RandomClass(id){
    this._id = id;
}

function.prototype.handlers = {}
function.prototype.handlers.HandlerOne = function(data){
    console.log("Handler one calling from ID: "+this._id+" with data: "+data);
}

var rc = new RandomClass(1);
rc.handlers.HandlerOne.call(rc, {"some": "data"});
//prints "Handler one calling from ID: 1 with data { "some" : "data" }