Trying to do this:
var c = {
x: 'other context'
};
var o = {
x: 'this context',
get otherContext () {
alert(this.x);
}.bind(c)
};
o.otherContext;
But I get a Syntax Error
:
Uncaught SyntaxError: Unexpected token .
You may ask, why I may want to change context on a getter. The use case that led me here dealt with creating a helper object that would retrieve DOM properties. The helper was defined inside another object that held a reference to the DOM element I needed properties from. So, this helper object is really just a proxy for some DOM methods, really, and I would do something like:
var ViewObject = function () {
this.el = document.getElementById('id');
var proxy = {
...
get left() {
return this.el.offsetLeft
}.bind(this)
...
};
};
IMHO this is a pretty valid use-case. And one where having the parent object's this
context would be useful. (Maybe proxy functions may be more adequate? Hmm...I didn't think about that. Still getters are ES5 and proxies are ES6 and only implemented by evergreens and Edge 13+, I think in the scope of ES5 the question still very much applies.)
Summary. The bind() method creates a new function, when invoked, has the this sets to a provided value. The bind() method allows an object to borrow a method from another object without making a copy of that method. This is known as function borrowing in JavaScript.
. bind() is used when you need to pass a callback (e.g. some sort of function reference), but you want the caller to call your function with a specific this value.
get() method in JavaScript is used to allow users to get the property from an object as a function. This method always returns the value of the property.
We use the Bind() method to call a function with the this value, this keyword refers to the same object which is currently selected . In other words, bind() method allows us to easily set which object will be bound by the this keyword when a function or method is invoked.
The problem is that method syntax doesn't use function expressions. It's a defined syntactic structure.
MethodDefinition[Yield] :
PropertyName[?Yield] ( StrictFormalParameters ) { FunctionBody }
GeneratorMethod[?Yield]
get PropertyName[?Yield] ( ) { FunctionBody }
set PropertyName[?Yield] ( PropertySetParameterList ) { FunctionBody }
PropertySetParameterList :
FormalParameter
Since it isn't a function expression, you don't have access to the functions methods or properties.
You can accomplish what you want with Object.defineProperty
.
var proxy = { ... };
Object.defineProperty(proxy, 'left', {
get: function() {
return this.el.offsetLeft;
}.bind(this)
});
For class proxies you might want to use something like this:
class Main {
constructor() {
this._adapter = new Adapter();
return this._createProxy();
}
_createProxy() {
return new Proxy(this, {
get(me, propertyName) {
if (typeof me._adapter[propertyName] === 'function') {
return me._adapter[propertyName].bind(me._adapter);
}
return (function () {
return me._adapter[propertyName];
}.bind(me._adapter))();
}
});
}
}
class Adapter {
constructor() {
this._foo = true;
this._yuk = 2;
}
get foo() {
return this._foo;
}
baz() {
return 4*this._yuk;
}
}
This way both, the getter and the method will be wrapped within the right context:
let main = new Main();
console.log(main.foo); // -> true
console.log(main.baz()); // -> 8
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With