Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending inheritance of `this` to methods / properties of an `object`

I'm not sure if I phrased the question title correctly; please consider the following to clarify...

(function() {
    var foo = {
        bar: function() {
            // Is it possible to reference 'this' as the
            // initializing 'object' aka 'e' and not 'foo' ?
            // The easy part, currently because 'this' refers to 'foo',
            // is returning 'this' aka 'foo' so that chaining can occur
            return this;
        },
        other: function() {
            return this;
        }
    };
    Event.prototype.foo = foo; 
}());

// usage
document.onmousemove = function(e) {
    e.foo.bar().other();
};

How would I go about having access to this within the methods / props of foo but having this refer to the initial object aka e and not foo ?


The best that I have come up with is this

(function() {
    var foo = function() {
        var _foo = this.foo;
        _foo._this = this; //recursive reference that I am VERY worried about
        return _foo;
    };
    foo.bar = function() {
        var _this = this._this; //_this refers to initial 'object', 'e'
        return this; //return 'foo' aka 'this' for function chaining
    };
    foo.other = function() {
        var _this = this._this;
        return this;
    };
    Event.prototype.foo = foo; 
}());

// usage
document.onmousemove = function(e) {
    e.foo().bar().other();
};

What I have currently works but I am worried about a couple of things...

1. The recursive reference of assigning e to e.foo._this

and

2. The redundancy of assigning e to e.foo._this, if this could be accessed as e instead of foo it would make 'things' more performant, especially in regards to something like a mousemove event.

jsFiddle Here


Also, Im trying to avoid something like this...

document.onmousemove = function(e) {
    e.foo.bar.call(e);
};

All suggestions are appreciated, Thanks for your time.

like image 610
Terry Avatar asked Oct 03 '22 19:10

Terry


2 Answers

With a subtle change to what you have you can make things simpler:

(function() {
    var foo = function() {
      this.foo.event = this;
      return this.foo;
    };
    foo.bar = function() {
      /// the event can be found in this.event
      return this;
    };
    foo.other = function() {
      /// the event can be found in this.event
      return this;
    };
    Event.prototype.foo = foo;
}());

// usage
document.onmousedown = function(e) {
    e.foo().bar().other();
};

This however is making a change to the shared object foo, you may wish to rewrite things so that e.foo() returns a new instance of foo instead, and move your other methods to foo's prototype.

(function() {
    var foo = function(event) {
      this.event = event;
    };
    foo.prototype.bar = function() {
      /// the event can be found in this.event
      return this;
    };
    foo.prototype.other = function() {
      /// the event can be found in this.event
      return this;
    };
    Event.prototype.foo = function() {
      return new foo(this);
    };
}());

This way you are creating a new instance of foo each time, but it means your addition of the event property is localised to that instance; the prototyped methods will be shared across all instances so it's not too bad from an optimisational point of view.

like image 103
Pebbl Avatar answered Oct 12 '22 15:10

Pebbl


Maybe that would work for you:

Use the apply method to change the this context in the called method and use this.foo to refer to foo:

(function () {
    var foo = function () {
        console.log(this);
        return this.foo;
    };
    foo.bar = function () {
        console.log(this);
        return this.foo;
    };
    foo.other = function () {
        console.log(this);
        return this.foo;
    };
    Event.prototype.foo = foo;
}());

// usage
document.onclick = function (e) {
    console.log(
        e.foo.apply(e).bar.apply(e).other.apply(e)
    );
};

FIDDLE

like image 27
basilikum Avatar answered Oct 12 '22 15:10

basilikum