Javascript - This
About
this is a variable that has a reference value to the scope (namespace)
Because Javascript is scoped on a object level, this is just by default a reference to the object/function where the code is living.
Proof: in the below code, printThis is a property function that lives inside the object obj, the keyword this is then a reference to the object obj.
obj = {
printThis: function (){
console.log(this);
},
prop1: 2
}
// printThis' will print the object 'obj' when asking to print 'this'
obj.printThis()
Generally, this is the local scope but it may be changed.
You can set this :
- in the call of a function (how the function was called)
- with bind
- automatically with the arrow function
otherwise it should be the function itself but not always. It may depends of the mode (non–strict/strict mode).
In JavaScript, class methods are not bound by default. If you forget to bind a method and pass it, it will get the value undefined when the function is actually called.
It is a part of how functions work in JavaScript. Generally, if you refer to a method without () after it, you should bind that method.
See also: Object - This
Example
Callback problem
- Create an object via class with a method
- Pass this method as callback (ie argument of a function)
- Call it
- this is not the object but the function.
To resolve it, you can use the arrow function.
Example:
- You should not pass
function (callback=myObject.myfunction){
//
}
- but
const callbackArrow = ()=>myObject.myfunction();
function (callback=callbackArrow){
//
}
Management
Initialization
Binding to global object
Binding to the global object is a problematic enough that ES5’s strict mode changes the default binding of this to undefined
A binding to the global scope with this will get the value:
- undefined in strict mode,
- or window in non strict mode
Example:
function hello() {
"use strict";
return "hello, " + this.name;
}
try {
hello();
} catch(e) {
console.log(e.message);
}
Event status
this is:
- onload an object Window when the document is loaded
- onclick an HTML element
Direct Assignment is not possible
this can not be assigned directly. The below code is illegal.
try {
eval('this = 2'); // eval is just there to be able to catch the referenceError
} catch (e) {
console.log(e.message);
}
Assignment with call and bind
this has int.
var double = function(b) {
return this * 2;
}
console.log(double.call(3));
console.log(double.bind(4)())
this as integer
this has int.
var double = function(b) {
return this * 2;
}
console.log(double.call(3));
Webtool (Chrome)
Example
What is this bound ?
The call expression determines the binding of this, also known as the call’s receiver.
function foo() {
console.log( this.bar );
}
var bar = "globalValue";
var obj1 = {
bar: "obj1Value",
foo: foo
};
var obj2 = {
bar: "obj2Value"
};
foo(); // "globalValue" - foo was called in the global scope - this = global scope (or window in a browser)
obj1.foo(); // "obj1" - foo was called in obj1 - this = obj1
foo.call( obj2 ); // "obj2" - foo was called with this = obj2 (the call function)
foo.bind( {bar: "bindValue" } )() // "bindValue" - this was bind to the parameter object
new foo(); // undefined - new sets this to a brand new empty object.
where:
Generally:
Example 2
var fn = function (one, two) {
if ("toString" in this) {
thisvalue = this.toString
} else {
thisvalue = "undefined"
}
if (one != undefined) {
onevalue = one.toString
} else {
onevalue = "undefined"
}
if (two != undefined) {
twovalue = two.toString
} else {
twovalue = "undefined"
}
console.log("*This* has the value '"+thisvalue+"', First argument has the value '"+onevalue+"', Second argument has the value '"+twovalue+"'\n\n");
};
this.toString = "Global";
var foo={ toString: "foo", fn : fn};
var bar={ toString: "bar" };
var darn={ toString: "darn" };
var rat={ toString: "rat" };
// Call of fn with differents context
console.log("foo.fn(bar,darn) gives:");
foo.fn(bar,darn);
console.log("fn(bar,darn) gives;");
fn(bar,darn)
console.log("fn.call(foo,bar,darn) gives;");
fn.call(foo,bar,darn)
console.log("foo.fn.call(rat,bar,darn) gives;");
foo.fn.call(rat,bar,darn)
console.log("setTimeout(fn, 1000) gives;");
setTimeout(fn, 1000);
console.log("setTimeout(foo.fn, 1000) gives;");
setTimeout(foo.fn, 1000);
console.log("setTimeout(function() { foo.fn() }, 1000) gives;");
setTimeout(function() { foo.fn() }, 1000);