Trying to get an object to identify its parent object without passing the parent into the child's instance

404 Views Asked by At

I'm having troubles finding detailed information on this issue. I would like to instantiate Bar() within Foo() without having to pass a pointer to Foo(). Or some way for Bar() to know it's a child of Foo(). Is this possible? Or am I already using a sufficient method?

Basically, I'm trying to avoid a call like:

var bar1 = new Bar(this,someValue);

Below I have a rough example of the method I'm currently using.

function Bar(p,val) {
    var par = p,
        value = val;
    this.__defineGetter__("value", function() {
        return par.dun.value + value;
    });
}

function Dun(val) {
    var value = val;
    this.__defineGetter__("value", function() {
        return value;
    });
}

function Foo() {
    var dun = new Dun(15);
    var bar1 = new Bar(this, 10);
    var bar2 = new Bar(this, 20);
    this.__defineGetter__("dun", function() {
        return dun;
    });
    this.__defineGetter__("bar1", function() {
        return bar1;
    });
    this.__defineGetter__("bar2", function() {
        return bar2;
    });
}
var myFoo = new Foo();
myFoo.bar1.value;

Thanks.

3

There are 3 best solutions below

5
On BEST ANSWER

No this is not possible, since there is no built in parent/child logic in JavaScript. They are just references to objects.

Update

oh sorry, I think I misunderstood your question. I´ve asked the same question some time ago: here. What you are trying to do, is to get the object that is "this" in the function that called the current function.

The answer is: you can´t do it...

But you could do it using the scope:

function Dun(val) {
    var value = val;
    this.__defineGetter__("value", function() {
        return value;
    });
}

function Foo() {
    var dun = new Dun(15);
    var bar1 = new Bar(10);
    var bar2 = new Bar(20);
    this.__defineGetter__("dun", function() {
        return dun;
    });
    this.__defineGetter__("bar1", function() {
        return bar1;
    });
    this.__defineGetter__("bar2", function() {
        return bar2;
    });
    function Bar(val) {
        this.__defineGetter__("value", function() {
            return dun.value + val;
        });
    }
}
var myFoo = new Foo();
myFoo.bar1.value;

PS: Not related to your question, but nice to know: since

function(val){}

is the same as

function(){
    var val = arguments[0];
}

you don`t have to create a new var and pass the arguments value to it. You can use the argument variable directly.

0
On

You need to give the child object one of the following:

  1. A direct pointer from one object to another, as in your example code.

  2. Unique information about the parent object, such that it can determine what that parent is indirectly through other means.

    For example, you could store all instances of Foo in a global registry object (either an object literal or array), which the child bar object could search through. It would be looking for the object that has a child bar equal to itself.1 In this way, the fact that it is a child of Foo is the unique identifier. Unless, of course, one bar can be shared across multiple foos. Then you're hosed. :)


1: The downside to this is that you're storing every instance of Foo ever created, which means they'll never be garbage collected: you'll be leaking memory, which could be bad if your environment sticks around for a while (e.g. a node.js app).

0
On

There is no way to automatically know the this pointer of the caller of a new. So, if you want to know what that this value is without passing it as part of the constructor, then you'd have to set some semi-global state that contains the appropriate information. You could do so like this:

function Bar(val) {
    var par = Bar.parent(),
        value = val;
    this.__defineGetter__("value", function() {
        return par.dun.value + value;
    });
}

// global methods and state on the Bar function
Bar.createContext = [];
Bar.push = function(o) {Bar.createContext.push(o);}
Bar.pop = function() {Bar.createContext.pop();}
Bar.parent = function() {return(Bar.createContext[Bar.createContext.length - 1]);}

function Dun(val) {
    var value = val;
    this.__defineGetter__("value", function() {
        return value;
    });
}

function Foo() {
    Bar.push(this);               // set global state
    var dun = new Dun(15);
    var bar1 = new Bar(10);       // don't need to pass "this" since it's in the global state
    var bar2 = new Bar(20);
    this.__defineGetter__("dun", function() {
        return dun;
    });
    this.__defineGetter__("bar1", function() {
        return bar1;
    });
    this.__defineGetter__("bar2", function() {
        return bar2;
    });
    Bar.pop();                    // restore global state
}
var myFoo = new Foo();
myFoo.bar1.value;

And, you can see it work here: http://jsfiddle.net/jfriend00/wMgBL/