After experimenting with inheriting contexts with the => feature that ES6 gives us I noticed that the this context can never be changed. Example:
var otherContext = {
a: 2
};
function foo() {
this.a = 1;
this.bar = () => this.a;
}
var instance = new foo;
instance.bar(); // returns 1
instance.bar.bind(otherContext)(); // returns 1
Without the => operator and using the function keyword:
function foo() {
this.a = 1;
this.bar = function () {
return this.a;
}
}
var instance = new foo;
instance.bar(); // returns 1
instance.bar.bind(otherContext)(); // returns 2
Therefore, if we receive a function from an external call or just have a function in a variable, how can we be sure if we are going to be able to bind a different this to it or if it will just inherit it from somewhere?
It sounds dangerous that javascript does not tell you anything, one might fall for a VERY subtle and difficult bug.
After experimenting with inheriting contexts with the => feature that ES6 gives us I noticed that the this context can never be changed. Example:
var otherContext = {
a: 2
};
function foo() {
this.a = 1;
this.bar = () => this.a;
}
var instance = new foo;
instance.bar(); // returns 1
instance.bar.bind(otherContext)(); // returns 1
Without the => operator and using the function keyword:
function foo() {
this.a = 1;
this.bar = function () {
return this.a;
}
}
var instance = new foo;
instance.bar(); // returns 1
instance.bar.bind(otherContext)(); // returns 2
Therefore, if we receive a function from an external call or just have a function in a variable, how can we be sure if we are going to be able to bind a different this to it or if it will just inherit it from somewhere?
It sounds dangerous that javascript does not tell you anything, one might fall for a VERY subtle and difficult bug.
Share Improve this question edited Oct 22, 2015 at 15:24 fos.alex asked Oct 22, 2015 at 15:18 fos.alexfos.alex 5,6274 gold badges18 silver badges18 bronze badges 5- I can't really see a question in there, is there something you doesn't understand about this behavior? – Karl-Johan Sjögren Commented Oct 22, 2015 at 15:23
- Yeah, this is my question: how can we be sure if we are going to be able to bind a different this to it or if it will just inherit it from somewhere? I added a question mark to clarify – fos.alex Commented Oct 22, 2015 at 15:24
- It's rather unusual that you're going to receinve a fat arrow function from some external source - and if so, it's not designed to be callable in other context. – Kuba Jagoda Commented Oct 22, 2015 at 15:30
-
1
If you're developing a method that receives a callback where the
this
value needs to be set, it's your job to document the method properly and it's the user's job to read the documentation and use the correct type of function. – user1106925 Commented Oct 22, 2015 at 15:37 - An arrow function is just as good as a bound function in that regard. – Bergi Commented Oct 22, 2015 at 22:11
2 Answers
Reset to default 8It is effectively just new syntax for bind
, so this doesn't introduce anything new in the way of gotchas.
var otherContext = {
a: 2
};
function foo() {
this.a = 1;
this.bar = function () { return this.a }.bind(this);
}
var instance = new foo;
log(instance.bar()); // returns 1
log(instance.bar.bind(otherContext)()); // returns 1
function log(value) {
document.body.appendChild(
document.createTextNode(value)
);
}
Therefore, if we receive a function from an external call or just have a function in a variable, how can we be sure if we are going to be able to bind a different this to it or if it will just inherit it from somewhere?
Because either:
- You'll have written that function in the first place or
- You'll have written a specification for how to call your function so that people know to pass in a function which makes use of
this
from a context you choose.
When using the function
keyword, the rules binding this
are fairly straight forward.
Either the invoking call sets this
(be it through .call
, .apply
or JavaScript setting this
when the function is called as a method) or this
gets a well-known value:
- In normal mode,
this
will be the window object. - In strict mode,
this
will be undefined.
With arrow functions, the rule is even simpler.
- There is no
this
keyword. (nor arguments, or a few others)
Which means that, inside an arrow function, this
is always bound to the outside context, because that is where this
es from.
So, in summary:
When using arrow functions, the value of this
always es from the outside context.