JAVASCRIPT
Core concepts
the this keyword
the this object (also called the Context Object) is determined by how the function is invoked
this means that the value of this is evaluated at run-time
wait... what?
context types:
- global context
- function context
- arrow function context (ES2015)
- object method
- getter methods
- constructor methods
- call, apply, bind
- DOM event handlers
Global context
In the global execution context (outside of any function), this refers to the global object, whether in strict mode or not.
console.log(this.document === document); // true
// In web browsers, the window object is also the global object:
console.log(this === window); // true
this.a = 37;
console.log(window.a); // 37
function context
Inside a function, the value of this depends on how the function is called.
function f1(){
return this;
}
f1() === window; // global object
function f2(){
"use strict"; // see strict mode
return this;
}
f2() === undefined;
Arrow function context
(ES2015)
In arrow functions, this is set lexically, i.e. it's set to the value of the enclosing execution context's this
var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject); // true
Object method context
When a function is called as a method of an object, its this is set to the object the method is called on.
var o = {
prop: 37,
f: function() {
return this.prop;
}
};
console.log(o.f()); // logs 37
GETTER method context
When a function is called as a method of an object, its this is set to the object the method is called on.
function sum(){
return this.a + this.b + this.c;
}
var o = {
a: 1,
b: 2,
c: 3,
get average(){
return (this.a + this.b + this.c) / 3;
}
};
Object.defineProperty(o, 'sum', {
get: sum, enumerable:true, configurable:true});
console.log(o.average, o.sum); // logs 2, 6
CONSTRUCTOR method context
When a function is used as a constructor (with the new keyword), its this is bound to the new object being constructed.
function C(){
this.a = 37;
}
var o = new C();
console.log(o.a); // logs 37
call, apply & bind context
Where a function uses the this keyword in its body, its value can be bound to a particular object in the call using the call or apply methods that all functions inherit from Function.prototype.
function add(c, d){
return this.a + this.b + c + d;
}
var o = {a:1, b:3};
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34
DOM event handlers context
When a function is used as an event handler, its this is set to the element the event fired from
function bluify(e){
console.log(this === e.currentTarget);
console.log(this === e.target);
this.style.backgroundColor = '#A5D9F3';
}
// Get a list of every element in the document
var elements = document.getElementsByTagName('*');
// Add bluify as a click listener so when the
// element is clicked on, it turns blue
for(var i=0 ; i<elements.length ; i++){
elements[i].addEventListener('click', bluify, false);
}
Closures
Closures are functions that refer to independent (free) variables (variables that are used locally, but defined in an enclosing scope). In other words, these functions 'remember' the environment in which they were created.
adica...
function init() {
var name = "JS Internship"; // name is a local variable created by init
function displayName() { // displayName() is the inner function, a closure
alert(name); // use variable declared in the parent function
}
displayName();
}
init();
Example I
function makeFunc() {
var name = "JS Inernship";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
Example II
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
Example III
Emulating private methods with closures
var counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
};
})();
console.log(counter.value()); // logs 0
counter.increment();
counter.increment();
console.log(counter.value()); // logs 2
counter.decrement();
console.log(counter.value()); // logs 1
Creating closures in loops:
A common mistake
var arr = [];
var i = 0;
for (i = 0; i < 10; i++) {
arr[i] = function() {
console.log(i);
}
}
arr[3]();
arr[4]();
What will this output?
Day II: JavaScript - Core concepts
By Andrei Cacio
Day II: JavaScript - Core concepts
this & closures
- 1,454