2014-09-25 63 views
0

这可能是重复的,如果是这样,我很抱歉。我浏览了几个问题,并没有找到与我的情况完全相符的情况(这可能是一个不好的迹象)。使对象子原型具有父对象的上下文

我有一类,说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 

回答

0

在这一点上提交这两个答案都是很好的选择(我会说是可以接受的),但我已经决定采取另一条路线(即导致对我的代码的最小修改:))。

与@ BlaShadow的回答相似,不是传递上下文并设置parentScope变量,我只是使用Javascript的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" } 
+0

另外,考虑到我问这个问题的方式,我毫不犹豫地将任何答案(包括我自己的答案)标记为“正确”。Javascript可能不容易做我所问过的事情,但我会稍微等一下,看看是否有其他答案。 – MandM 2014-09-26 17:34:50

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) 
+0

嗯...传递自己作为上下文是有趣的,我相信会工作得很好。感谢您的建议!不过,我仍然坚持直接访问父上下文的方式。 – MandM 2014-09-25 21:13:33

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 
+0

也很有趣,我没有想过把它移到它自己的类。我想没有理由不应该这样做。你能否在Handlers.prototype定义中解释'constructor:Handlers'这一行? – MandM 2014-09-25 21:25:20

+0

@MandM每个函数都有一个'prototype',它有一个指向那个函数的'constructor'成员。在这里,由于我完全用一个新对象来替换原型(为了从对象字面符号中受益),所以我需要手动设置'constructor'成员*。代码在没有它的情况下仍然可以工作,但是如果有人依赖于'rnd.handlers.constructor',它将不会返回所期望的。 – plalx 2014-09-26 12:24:02