Getting a 'this' link to a second level prototype

I am absolutely sure that this is impossible, but I would like to know if anyone has brilliant ideas on how to make this possible.

I want the following code to work:

var x = new foo();
x.a.getThis() === x; // true

In other words, I want to x.a.getThishave a link to thislike xin this case. It makes sense?

To make this work alone , the level is very simple:

function foo(){}
foo.prototype.getThis = function(){ return this; }
var x = new foo();
x.getThis() === x; // true

One thing, I want this to work as a prototype, not to β€œcheat” by manually binding to this:

function foo(){
    this.a = {
        getThis : (function(){ return this; }).bind(this)
    };
}

Although the above is the perfect functional example of what I'm trying to achieve, I just don't want all the extra features for each instance :)

FYI, , Cassandra node, super-column β†’ column-family β†’ foo.a.b foo .

+3
4

- . , "", , this, . JS , .

, script .

foo = ->
  @a = getThis: => this

=> , . .

JS:

var foo;
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
foo = function() {
  return this.a = {
    getThis: __bind(function() {
      return this;
    }, this)
  };
};

, , .


, this , "" .

var A = function(owner) {
  this.owner = owner;
};
A.prototype.getThis = function() {
  return this.owner;
};
var Foo = function() {
  this.a = new A(this);
};

var foo = new Foo();

if (foo.a.getThis() === foo) {
    alert('Happy dance');
} else {
    window.location = 'https://commons.lbl.gov/download/attachments/73468687/sadpanda.png';
}

http://jsfiddle.net/4GQPa/

script , :

class A
  constructor: (@owner) ->
  getThis: -> @owner

class Foo
  constructor: -> @a = new A(this)

foo = new Foo()
if foo.a.getThis() is foo
  alert 'Happy Dance'
else
  window.location = 'https://commons.lbl.gov/download/attachments/73468687/sadpanda.png'
+3

, . , , "" β†’ .

this , , β†’ . :

var x = {
  a : {
    b: function() {return this;}
  }
}

x.a.b(), b this a. :

var c = x.a.b;
c(); // *this* is the global object

x.a.b.call(someOtherObject);

β†’ this ?

0

Answering my own question, because someone might find it useful. Not sure if I will return to this decision or to Squeegy. Functions are defined only once, and then the contained object is cloned and contains parent = this:

function foo(){
    var self = this, nest = this.__nestedObjects__ || [];

    nest.forEach(function(prop){
        self[prop] = extend({ parent : self }, self[prop]);
    });
}

// bound like this so that they're immutable
Object.defineProperties(foo.prototype, {
    bar : {
        enumerable : true,
        value : {
            foobar : function(){
                return this.parent;
            },
            foo : function(){},
            bar : function(){}
        }
    },
    __nestedObjects__ : { value : ['bar'] }
});

var fooInst = new foo();
console.log(fooInst.bar.foobar() == fooInst);

or based on Squeegy solution:

function foo(){
    for(var cls in this.__inherit__){
        if(!this.__inherit__.hasOwnProperty(cls)){ continue; }

        this[cls] = new (this.__inherit__[cls])(this);
    }
}

var clsA;
// bound like this so that they're immutable
Object.defineProperties(foo.prototype, {
    __inherit__ : { value : {
        bar : clsA = function(parent){
                Object.defineProperty(this, '__parent__', { value : parent });
            }
        }
    }
});

clsA.prototype = {
    foobar : function(){
        return this.__parent__;
    }
};

var fooInst = new foo();
console.log(fooInst.bar.foobar() == fooInst);
0
source

Just curious: will it do what you want?

function Foo(bar){
    var justme = this;
    this.a = { fromfoo: {
                foobarme: function(){
                            return '(from [Foo instance].a.fromfoo.foobarme) '+
                             this.root.foobarred();
                         },
                 root: justme
               }
              };
    this.bar = bar || 'foobar';
    this.a.foobar = 'barfoo';
}
Foo.prototype.foobarred = function(){
     return 'hi, I am method foobarred from Foo, '+
            'and this is my instance property \'bar\': '+
             this.bar;
};
var b = new Foo('instance b'),
    c = new Foo('instance c');
alert(b.a.fromfoo.root === b); //=> true
alert(b.a.fromfoo.foobarme()); //=> [(from ... 'bar': ] instance b
alert(c.a.fromfoo.foobarme()); //=> [(from ... 'bar': ] instance c
0
source

All Articles