Understanding Javascript

These are equal, one is es6 the other is es5.

var EventEmitter = require('events');
var util = require('util');

class Greetr extends EventEmitter {
    constructor() {
        super();
        this.greeting = 'Hello world!';
    }

    greet(data) {
        console.log(this.greeting + ': ' + data);
        this.emit('greet', data);
    }
}

function Greetr() {
    EventEmitter.call(this);
    this.greeting = 'Hello world!';
}

Greetr.prototype = Object.create(EventEmitter.prototype);
Greetr.prototype.constructor = Greetr;

Greetr.prototype.greet = function(data) {
    console.log(this.greeting + ': ' + data);
    this.emit('greet', data);
}

Javascript is synchronous. Code is executed one line at a time and in order. Only one thing is happening at a time.

Execution Stack

Javascript has an execution stack. First line of code is running in the Global Execution Context. When it enters a function, an execution context is placed upon the Global Execution Context.

Whichever Execution Context is on top of the stack is currently running.

Every function creates a new execution context. This execution context runs through the create phase and then executes the code line by line.

function b() {

}

function a() {
  b();
}

a();

It doesn’t really matter where these functions are defined lexically because they are all in memory.

Each Execution Context gets its own Variable Environment, its own memory space

Function Execution Context - call, apply, bind

Variable Environment -> this -> outer environment

A way to control the this variable ends up being when the execution context is created. That is where call, apply and bind come in.

Functions are just a special type of object. All functions have access to a call, apply and bind function.

var person = {
    firstname: 'John',
    lastname: 'Derp',
    getFullName: function () {
        var fullname = `${this.firstname} ${this.lastname}`;
        return fullname;
    }
}

var logName = function(lang1, lang2) {
    console.log(`Logged: ${this.getFullName()}`)
    console.log(`${lang1} ${lang2}`)
    console.log('---------');
}

        // .bind creates a copy of the logName function with this pointing at person
var logPersonNameBind = logName.bind(person);

logPersonNameBind('en', 'es');
// => Logged: John Derp
// => en es

       // .apply executes the function
logName.apply(person, ['en', 'es']);
// => Logged: John Derp
// => en es

       // .call executes the function
logName.call(person, 'en', 'es');
// => Logged: John Derp
// => en es



(function(lang1, lang2) {
    console.log(`Logged: ${this.getFullName()}`)
    console.log(`${lang1} ${lang2}`)
    console.log('---------');
}).apply(person, ['es', 'en']);
// => Logged: John Derp
// => es en


// function borrowing
var person2 = {
    firstname: 'Jane',
    lastname: 'Doe'
}

console.log(person.getFullName.apply(person2));
// => Jane Doe



// function currying - creating a copy of a function but with some preset parameters
function multiply(a, b) {
    return a*b;
}

// this will permanently set the first paramter in multiply to 2
var multiplyByTwo = multiply.bind(this, 2);
console.log(multiplyByTwo(5));
// => 10

Post Content