0
function Foo(){

}
Foo.prototype={
    foo:'some text'
    ,bar:function(){
        console.log('Want to be able to retrieve foo of Foo',this.foo);
    }
}

var instance=new Foo();
instance.bar.apply({});

Here is link to jsfiddle:

http://jsfiddle.net/dnJFt/1/

I was trying to play with scopes putting class building inside wrapper with var self inside it. And after returning instance of Class, refer it to var self like that:

function Foo() {
    var self;
    function Foo_in(){

    }
    Foo_in.prototype={
        foo:'some text'
        ,bar:function(){
            console.log('Want to be able to retrieve foo of Foo',self);
        }
    }
    return self=new Foo_in();
}

var instance=new Foo();
instance.bar.apply({});

Here is link to jsfiddle: http://jsfiddle.net/dnJFt/2/

But my solution is bad, because each time i'm rebuilding Class and it's prototype methods.

Is there an easier solution?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Somebody
  • 9,316
  • 26
  • 94
  • 142

2 Answers2

0

Try in this way:

var Foo = (function () {
    var Foo_in = function (){};
    Foo_in.prototype={
        foo:'some text',
        bar:function(){
            console.log('Want to be able to retrieve foo of Foo',self);
        }
    }
    var self = new Foo_in();
    return Foo_in;
})();

With this code you create the class in the auto-calling function scope and you declare the self variable inside that scope so that it will be accessible inside class methods, then you return a reference of the class that will be assigned to the global Foo variable. In this way you get a reference to the self variable and you create the class only one time.

mck89
  • 18,918
  • 16
  • 89
  • 106
  • It would make more sense to just store the `Foo_in.prototype` object in a `proto` variable. – Šime Vidas Dec 28 '11 at 13:53
  • http://jsfiddle.net/dnJFt/3/ here is the reason it won't work for me. I just want to be able to use another context while have access to parent context. – Somebody Dec 28 '11 at 14:02
  • Yes it does not work because self is an instance of the class and if you want to change that property you must change the self instance, every other instance is a different object – mck89 Dec 28 '11 at 14:12
  • @Beck Assigning to `instance.foo` will shadow the `Foo.prototype.foo` value. Only `instance` has access to the new value, so if you want to access that value from withing `bar`, you need to pass in the `instance` object into `bar`... – Šime Vidas Dec 28 '11 at 14:12
  • So the verdict is to loose performance and use my initial solution or to pass initial instance with different context as parameters inside bar() – Somebody Dec 28 '11 at 14:16
  • Or you can create a normal class and avoid using apply or call methods so you can use "this" and refer to the current instance. – mck89 Dec 28 '11 at 14:19
  • @Beck Your initial solution is not good since it rebuilds the class (as you mentioned). The solution proposed by mck is acceptable. I have also proposed my own version of that technique in my updated answer... – Šime Vidas Dec 28 '11 at 14:34
0

You could pass the Foo.prototype object as an argument:

function Foo() {}

Foo.prototype = {
    foo: 'some text',
    bar: function ( proto ) {
        console.log( 'foo: ', proto ? proto.foo : this.foo );
    }
}

var instance = new Foo();

So....

instance.bar() // 'some text'
instance.bar.apply( {}, [ Foo.prototype ] ) // 'some text'

Live demo: http://jsfiddle.net/wpyZN/


Alternative usage:

instance.bar() // 'some text'
instance.bar.apply( {}, [ instance ] ) // 'some text'

Live demo: http://jsfiddle.net/wpyZN/1/


Update: My take on the closure solution:

var Foo = (function () {
    function F() {}

    var proto = F.prototype = {
        foo: 'some text',
        bar: function () {
            console.log( 'foo: ', proto.foo );
        }
    }
    return F;
})();


var instance = new Foo();
instance.bar.apply( {} );

Live demo: http://jsfiddle.net/KT7vU/

So, the bar method uses the proto reference to access the foo value...

Doing this.foo inside bar doesn't work (the apply-invocation changed the this value, so that it no longer points to the instance). Therefore, we have to provide a manual reference to the prototype object which holds the desired foo value. The most appropriate way to do such is the one provided in my code above...

Šime Vidas
  • 182,163
  • 62
  • 281
  • 385
  • Forget about prototype already. Bug i guess you are right. The only solution is to pass instance itself as parameter. – Somebody Dec 28 '11 at 14:13
  • @Beck The value that you are trying to access - `'some value'` - is assigned to `Foo.prototype.foo`. So, the prototype object `Foo.prototype` is obviously needed in order to access the desired value. If you don't want to pass in the prototype object, you could pass in the instance: `instance.bar.apply( {}, [ instance ] );` - this would also work... – Šime Vidas Dec 28 '11 at 14:19