Reputation: 1341
I'd like to 'proxy' (not sure if that's the term at all) a function inside a function object for easy calling.
Given the following code
function Soldier() {
this.el = $("<div></div>").addClass('soldier');
this.pos = this.el.position; // $(".soldier").position(), or so I thought
}
In the console:
s = new Soldier();
$("#gamemap").append(s.el); // Add the soldier to the game field
s.pos === s.el.position // this returns true
s.el.position() // Returns Object {top: 0, left: 0}
s.pos() // Returns 'undefined'
What am I doing wrong in this scenario and is there an easy way to achieve my goal (s.pos()
to return the result of s.el.position()
) ?
I thought about s.pos = function() { return s.el.position(); }
but looks a bit ugly and not apropriate. Also I'd like to add more similar functions and the library will become quite big to even load.
Upvotes: 1
Views: 74
Reputation: 7004
When you're calling s.pos()
, its this
context is lost.
You can simulate this behavior using call()
:
s.pos.call(s); // same as s.pos()
s.pos.call(s.el); // same as s.el.position()
This code is actually ok:
s.pos = function() { return s.el.position(); }
An alternative is using bind()
:
s.pos = s.el.position.bind(el);
You can use the prototype, that way the functions will not be created separately for every object:
Soldier.prototype.pos = function(){ return this.el.position(); }
Upvotes: 2
Reputation: 10874
It's because the context of execution for position
method has changed. If you bind the method to work inside the element context it will work.
function Soldier() {
this.el = $("<div></div>").addClass('soldier');
this.pos = this.el.position.bind(this.el);
}
var s = new Soldier();
$("#gamemap").append(s.el);
console.log(s.pos());
Upvotes: 1
Reputation: 664548
I'd recommend to use the prototype:
Soldier.prototype.pos = function() { return this.el.position(); };
Not ugly at all, and quite performant actually.
If you want to directly assign it in the constructor, you'll need to notice that the this
context of a s.pos()
invocation would be wrong. You therefore would need to bind
it:
…
this.pos = this.el.position.bind(this.el);
Upvotes: 1