Suppose I have following code:
var Model = function() {};
Model.prototype.a = function() {//do smth
Model.prototype.a.on = function() {//do smth
var m = new Model();
m.a();
m.a.on();
Now I need reference to specific object m from m.a() and m.a.on() calls. When calling m.a(), i have this referring to m.
Is it possible to get reference to m from m.a.on() call somehow?
It's a very bad idea to do so, as it leads to very strange behaviour in some cases, but it's possible:
var Model = function(x) { this.x = x };
Object.defineProperty(Model.prototype, 'a', (function() {
var lastSelf;
function get() { return lastSelf.x }
get.on = function () { return lastSelf.x * 2 };
return { get() { lastSelf=this; return get } };
})());
var m = new Model(17);
console.log(m.a(), m.a.on());
Why? I see your answer below, trying to realize what are bad cases.
You can't pass a
through the variable.
You must grant access to on
immediately after getting property a
of the same object:
var Model = function(x) { this.x = x };
Object.defineProperty(Model.prototype, 'a', (function() {
var lastSelf;
function get() { return lastSelf.x }
get.on = function () { return lastSelf.x * 2 };
return { get() { lastSelf=this; return get } };
})());
var m1 = new Model(1), m2 = new Model(3);
console.log(m1.a(), m2.a(), m1.a.on(), m2.a.on()); // 1 3 2 6 - ok
var a1 = m1.a, a2 = m2.a;
console.log(m1.a(), m2.a(), a1.on(), a2.on()); // 1 3 6 6 - ooops!
console.log(m1.a(), m2.a(), m1.a(), a1.on(), a2.on()); // 1 3 1 2 2 - ooops!
And the other solution, but with using __proto__
. According to ES6 this solution is valid for browser enviroments and for server enviroments __proto__
have to be replaced by Object.setPrototypeOf
. Be sure to check browser support and other warnings.
This solution adds 1 function and 1 object per each instance.
function Model(x) {
this.x = x;
this.a = function () { return Model.prototype.a.call(this, arguments) };
this.a.__proto__ = Object.create(Model.prototype.a);
this.a.this = this;
}
Model.prototype.a = function () { return this.x };
Model.prototype.a.on = function () { return this.this.x * 2 };
var m1 = new Model(1), m2 = new Model(3);
console.log([m1.a(), m2.a(), m1.a.on(), m2.a.on()] == "1,3,2,6");
var a1 = m1.a, a2 = m2.a;
console.log([m1.a(), m2.a(), a1.on(), a2.on()] == "1,3,2,6");
console.log([m1.a(), m2.a(), m1.a(), a1.on(), a2.on()] == "1,3,1,2,6");