Closures & Prototypal Inheritance
In js functions are high order function and objects at the same time.
Closures
Example:
function a() {
let grandpa = 'grandpa';
return function () {
let father = `father`;
return function () {
let son = 'son';
return `${grandpa} > ${father} > ${son}`;
};
};
}
console.log(a()()());
Closures allow function to access to the variables from the lexical scope even when they are called outside of this lexical scope.
Consider the following piece of code:
const array = [1, 2, 3, 4];
for (var i = 0; i < array.length; i++) {
setTimeout(function () {
console.log("I'm at index " + i);
}, 10);
}
It returns 4 times 'I'm at index 4'
. The easiest way to fix it is to change var
to let i = 0
. Because let
works with block scopes.
The another solution (if we can’t use let
for some reason), we can use closure with IIEF:
const array = [1, 2, 3, 4];
for (var i = 0; i < array.length; i++) {
(function(c) {
setTimeout(function () {
console.log("I'm at index " + c);
}, 10);
})(i);
}
Prototypes
We can get an access to base object (prototype) by obj.__proto__
.
See on the following code:
let dragon = {
name: 'Tanya',
fire: true,
fight() {
return 5;
},
sing() {
let message = this.fire
? `I'm ${this.name}, the breather of fire`
: `I'm ${this.name}`;
console.log(message);
return message;
},
};
let lizard = {
name: 'Kiki',
};
dragon.sing();
We can make dragon
object to be the base object of a lizard
the following way:
lizard.__proto__ = dragon;
But we shouldn’t use it, because of bad performance.
We can check if one object is prototype of another we can use isPrototypeOf
function:
dragon.isPrototypeOf(lizard)
We can check if property is own by lizard.hasOwnPropery(prop)
:
for (let prop in lizard) {
if (lizard.hasOwnProperty(prop)) {
console.log('Prop: ', prop);
}
}
Ways to inherit
First:
let lizard = Object.create(dragon);
Prototype property
Only functions have a prototype
property.
Object
is a function.
Object.prototype
is a base object.
How we can modify existing functionalty:
Date.prototype.lastYear = function () {
return this.getFullYear() - 1;
};
let date = new Date('1900-10-10');
console.log(date.lastYear());