‘this’ keyword

‘this’ in Global Context:

  • ‘this’ refers to window.

‘this‘ in a function call: 

  • In most cases, the value of a function’s ‘this’ argument is determined by how the function is called.  This means the ‘this’ value may be different each time a function is executed.
  • In “use strict” mode, ‘this’ is defaulted to undefined and prevents us from assigning values to undefined, and accidentally creating global variables.

‘this’ in a constructor call:

  • When a function is called as a constructor (with a ‘new’ keyword), a new object is created and set as the function’s ‘this’ argument.
function Person (firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

const person = new Person('John', 'Doe');

console.log(person) // { firstName: 'John', lastName: 'Doe' }

‘this’ in method call:

  • When a function is called as a method of an object, that function’s this argument is set to the object the method is called on. That object is called the receiver of the function call.
  • Oftentimes, the receiver gets lost when we invoke a method as a function. This happens particularly often when passing a method as a callback to another function. (example below – ‘this’ context is lost when assigning method to greet)
const person = {
   firstName: 'John',
   sayHi() {
     console.log(`Hi, my name is ${this.firstName}!`);
   }
};

const greet = person.sayHi;
greet(); // Hi, my name is undefined!
  • Use a wrapper function or .bind method to workaround this problem.

Specify ‘this’ using .call() or .apply():

  • Use .call and .apply to call a function with an explicit ‘this’ argument
  • .call accepts arguments as a comma separated list
  • .apply accepts arguments as an array.
const numbers = [10, 20, 30, 40, 50]

const slice1 = numbers.slice(1, 4); //syntactic sugar for the following:
const slice2 = numbers.slice.call(numbers, 1, 4);
const slice3 = numbers.slice.apply(numbers, [1, 4]);

// slice1, slice2, slice3 all return [20, 30, 40]

Hard-bind a function’s ‘this’ using .bind():

  • permanently tie a function’s ‘this’ argument to a specific value. It creates a new bound function that calls the original function with the provided ‘this’ argument, no matter how that bound function is called.
const person = {
   firstName: 'John',
   sayHi() {
     console.log(`Hi, may name is ${this.firstName}!`);
   }
};

const greet = person.sayHi.bind(person);
greet(); // Hi, my name is John!

const otherPerson = {
   firstName: 'Jane'
};

greet.call(otherPerson); // Hi, my name is John! 

‘this’ can be captured with an Arrow Function (ES6):

  • An arrow function doesn’t have its own ‘this’. Instead, it uses the ‘this’ value from its enclosing execution context.
  • When an arrow function is created, it permanently captures the surrounding ‘this’ value. Neither .call() nor .apply() can change the ‘this’ value later.
  • Arrow functions cannot be used as constructors.
  • Solves issues of incorrect ‘this’ values within callback functions.
const counter = {
  count: 0,
  incrementPeriodically() {
    setInterval(() => {
      console.log(this.count++);
    }, 1000);
  }
};

counter.incrementPeriodically();

// 'this' stays bound to counter object inside setInterval.

‘this’ in classes:

  • Within the constructor of a class, this refers to the newly created object.  Within a method, however, this might refer to another value if the method is called as an ordinary function. Just like any other object method, class methods can lose their intended receiver this way.
class Person {
  constructor (firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.sayHi = this.sayHi.bind(this);
  } 

  sayHi() {
    console.log(`Hi, my name is ${this.firstName}!`);
  } 
}

const person = new Person('John', 'Doe'); 
const greet = person.sayHi; 

greet(); // Hi, my name is John 
// ('this' is bound to object in constructor)
  • You can also bind this using class fields with arrow functions:
class Person {
  // class field with arrow function
  sayHi = () => {
    console.log(`Hi, my name is ${this.firstName}!`);
  } 
  constructor (firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  } 
}

const person = new Person('John', 'Doe'); 
const greet = person.sayHi; 

greet(); // Hi, my name is John 
// ('this' is bound to instance in class fields w/ arrow functions)

*Use a transpiler like Babel to translate ES6 into ES5 if using class fields and arrow functions.

Advertisements
‘this’ keyword

Data Modeling & Classes

Functional:

  • constructor and methods are wrapped in one class function.
  • return instance object at the end.
var ClassName = function {
  var newInstance = {};
  newInstance.methodOne = function () {
  };

  newInstance.methodTwo = function () {
  };

  return newInstance {}; 
};

Functional-shared:

  • Methods are stored in a separate object outside constructor function.
  • Uses extend to give instance access to method object.
  • Return newInstance inside constructor.
  • Methods uses ‘this’ keyword to reference newInstance.
var ClassName = function {
  var newInstance = {};
  extend(newInstance, classMethods);
  return newInstance; 
}

var classMethods = {};

classMethods.methodOne = function () {
};

classMethods.methodTwo = function () { 
}; 

Prototypal:

  • Methods are stored in a separate object outside constructor function.
  • Uses Object.create to access methods
  • Return newInstance inside constructor.
var ClassName = function {
  var newInstance = Object.create(classMethods);
  return newInstance; 
}

var classMethods = {};

classMethods.methodOne = function () {
};

classMethods.methodTwo = function () { 
}; 

Pseudoclassical (most commonly used pattern)

  • Uses the ‘new’ keyword to instantiate a new instance.  (‘new’ replaces the need for Object.create and returning the object inside the constructor).
  • Methods stored on the prototype chain.
  • Uses ‘this’ keyword to reference the new instance.
var ClassName = function {
  this.length = 5;
}

ClassName.prototype.methodOne = function () {
};

ClassName.prototype.methodTwo = function () { 
};

var newInstance = new Class();

 

Data Modeling & Classes

Partial Application (Currying)

Partial Application or currying is a feature that Function.prototype.bind offers.

This allows you to pass in some arguments at bind time and get back a new function that invokes the original function using the rest of the arguments at call time.

For example:

Screen Shot 2017-12-01 at 8.02.50 PM

  • null is passed in because we’re not working with ‘this’ in this example.
  • the first argument we pass in at bind time is 2.
  • doubler is the function we get back after binding.
  • every invocation of doubler is invoking the original multiply function with the remaining arguments.

 

Partial Application (Currying)

setInterval vs setTimeout

Both are Javascript’s timing events.

setInterval(function(), milliseconds):

  • Executes a function repeatedly, with a fixed time delay between each call to that function. (useful for countdown)
  • clearInterval() takes an in-scope variable which points to the setInterval method and stops the function from looping.

 

setTimeout(function(), milliseconds):

  • Executes a function once, after waiting a specified delay.
  • clearTimeout() stops the execution, thus disabling it from running again in the future.

Notes:

  • 1000 milliseconds = 1 second
setInterval vs setTimeout

$(document).ready() vs. window.onload()

SUMMARY: Run Javascript after the DOM has loaded but before the entire page has fully loaded (for faster loading time) because your code relies on working with the DOM.  This can be done with $( document).ready() in jQuery.

$(document).ready() in jQuery executes when the DOM (Document object model) is loaded on your page. DOM means all the html tags/script. It will not wait for the images, frames to be fully loaded.  It is the earliest stage in page load process and executes a bit earlier than window.onload(), thus less time-consuming for the browser.

window.onload() in JavaScript executes when all the content on your page is fully loaded including the DOM, asynchronous javascript, frames, images, and other assets.

PAGE LOADING STAGES:

  1. Browser makes a request to download the page
  2. Raw markup and DOM is loading (does not include external sources such as images and stylesheets).  DOMContentLoaded event occurs at the end of this stage and you can set your code to run at this time with $(document).ready().
  3. Page is fully loaded with images and stylesheets.  Load event occurs at the end of this stage and you can execute your code to run at this time with window.onload().  (You rarely need to do this unless you need to work with the images or assets in your code).
$(document).ready() vs. window.onload()