Essential part of Javascript, every function in Javascript has context, how does it work, how does it manipulate it, and what changes in the strict mode ( 'use strict'
)?
Essential part of Javascript, every function in Javascript has context, how does it work, how does it manipulate it, and what changes in the strict mode ( 'use strict'
)?
In JavaScript, the execution context of a piece of code - which defines what its lexical scope, among other things - has a property called ThisBinding
, which can be accessed at any time through the keyword this
. This property - present even when you are not inside a function and / or this function is not an object's method - is popularly known as the context [function].
Initially (ie at "top-level") this
corresponds to a reference to the global object . In browsers, it is called window
, and is self-referencing . When interpreting a code through eval
, it is kept as is.
When calling a function, it changes as follows:
If this function is called in the form of a method (i.e. name, period, name, parentheses) this
becomes a reference to the object that was "target" of the call:
obj.f(); // Dentro de "f", this === obj
As pointed out by @bfavaretto, if the object is a primitive type (as a number), then the this
can suffer coercion for an object . This does not occur in strict mode.
Number.prototype.foo = function() {
console.log(typeof this);
}
10.0.foo(); // "number" no modo estrito, "object" caso contrário
If you use one of the methods call
, apply
or bind
, this
is explicitly assigned:
f.call(obj, foo, bar); // Dentro de "f", this === obj
f.apply(obj, [foo]); // idem
f.bind(obj); // idem
This is worth even though the function has been referenced in the form of an "object method":
obj.f.call(bar); // Dentro de "f", this === bar
In strict mode, what is passed as the first parameter will be this
, without modification. Otherwise, there may be the same coercion as the previously mentioned object or, if the value passed as a parameter is null
or undefined
, this
returns to the global object:
f.call(20); // 20 no modo estrito, Number(20) caso contrário
f.call(null); // null no modo estrito, window caso contrário
f.call(); // undefined no modo estrito, window caso contrário
If the function is called in the "normal" form (i.e. name, parentheses), then of the two one:
In strict mode, this
will be undefined
:
"use strict";
f(); // Dentro de "f", this === undefined
In all other cases, this
is again a reference to the global object:
f(); // Dentro de "f", this === window
... which often causes confusion:
var obj = {
f:function() {
function g() {
console.log(this); // this não é obj, e sim window ou undefined
// (conforme o modo, estrito ou não)
}
g(); // Espera-se que imprima "obj", mas não é o que ocorre
}
}
The main way of manipulating the context, as we have seen, is through the methods call
, apply
and bind
. The latter creates a "view" of the original function where this
is "tied" to the parameter used, and can not be modified (a kind of #, also allowing you to fix the first N arguments) - not even by other methods:
function f() {
console.log(this);
}
var x = f.bind(10); // this está amarrado a 10
x.call(20); // não muda o this, ainda imprime 10
As for the strict mode, the main impact in this context is the one exposed above - where this
does not refer to the global object when omitted (i.e. when not explicitly assigned). This has an impact on security because it facilitates sandboxing of unreliable code. There are many other impacts that the strict mode exerts on execution contexts and scope, but nothing that affects the operation of this
(even eval
continues behaving in the same way in both modes).