Javascript-What we should Know

4 minute read

Let’s explore what we should know about Javascript.

Data Types and structure types

  • Data types (primitives)

    • undefined
    • boolean
    • number
    • string
    • bigint
    • symbol
  • Structure Types

    • object (array, map, set, classes with new keyword)
    • function
    • null (typeof instance === “object”)

Immutable Types(number, string, null, undefined, boolean)

Mutable Types:(object, array, map, set, function)

Strict Mode

Strict mode is declared by adding “use strict”; to the beginning of a script or a function. Using a variable, without declaring it, is not allowed

"use strict"; // global scope.
//x = 10; // throws ReferenceError, variable should be declared with strict mode.
(function () {
  "use strict"; // function scope
})();

Hoisting

Hoisting is the process of moving all the declarations (variables and functions) to the top of the scope.

"use strict";

(function () {
  // console.log(a); // ReferenceError: a is not defined

  console.log(v); // undefined
  var v = 10; // ES5: var -- The declaration (var v;) will be hoisted on the top of the scope (initialiaztion (v=10) of the variable is not hoisted).
  console.log(v); // 10

  // Variables defined with let and const are hoisted to the top of the block, but not initialized.
  // it cannot be used until it has been declared.

  // console.log(z);
  // let z; // ReferenceError: Cannot access 'z' before initialization

  // console.log(z);
  // const y; // const should be initilized.
  // const z = "z"; // ReferenceError: Cannot access 'z' before initialization

  //   var a = "a";
  //   var a;
  //   console.log(a); // a

  //   let b;
  //   let b; // SyntaxError: Identifier 'b' has already been declared

  //   const c;
  //   const c; // SyntaxError: Missing initializer in const declaration

  //   var d;
  //   var d;
  //   console.log(d); // undefined

  //   var g = "g";
  //   var g;
  //   console.log(g); // g

  //   if (true) {
  //     let e = "e";
  //     console.log(e); // e
  //   }
  //   let e = "ee";
  //   console.log(e); // ee

  //   if (true) {
  //     const f = "f";
  //     console.log(f); // f
  //   }
  //   const f = "ff";
  //   console.log(f); // ff
})();

Keyword this

The use of “this” varies depending on the context and also depending on the mode of JavaScript (strict mode or not).

We’re going to explore different use cases.

  • By default, “this” refers to the global object (window in browser, global in node):
if (typeof window !== "undefined") {
  console.log(this === window); // browser context
} else {
  console.log(this === global); // node context
}
  • “this”, when invoked inside a function, refers to the global object. In strict mode, it refers to undefined.
(function () {
  // strict mode is not enabled
  // "this" refers to global context

  console.log(`(this === window) => ${this === window}`); // true
})();
(function () {
  "use strict";

  // strict mode is enabled
  console.log(`(this === undefined) => ${this === undefined}`); // true
})();
  • “this”, refers to the new instance.
(function () {
  function Person(name, surname) {
    this.name = name;
    this.surname = surname;
    this.fullName = function () {
      return `${this.name}  ${this.surname}`;
    };
  }
  console.log(new Person("richard", "stellman").fullName());
})();
  • “this”, refers to the invoker object.
(function () {
  const o = {
    attr: "val",
    func: function () {
      return this === window; // "this" refers to the object
    },
  };

  let func = o.func;

  // true => "this" refers to global context.
  console.log(func());

  // false => "this" refers to the object context.
  console.log(o.func());
})();

(function () {
  "use strict";
  const o = {
    attr: "val",
    func: function () {
      return this === window; // "this" refers to the object
    },
  };

  let func = o.func;

  // false => "this" refers to the object context.
  console.log(func());

  // false => "this" refers to the object context.
  console.log(o.func());
})();
  • “this” refers to a custom instance with bind, apply,call.
(function () {
  "use strict";
  function Person(name) {
    this.name = name;
    this.displayName = function () {
      console.log(this.name);
    };
  }

  // Every function has call, bind, and apply methods.
  // These methods can be used to set a custom value to this in
  // the execution context of the function.

  let p1 = new Person("myname1");
  p1.displayName(); // myname1

  let p2 = new Person("myname2");
  p2.displayName(); // myname2

  let f = p1.displayName.bind(p2);
  f(); // myname2

  p1.displayName.call(p2); // myname2
  p1.displayName.apply(p2); // myname2
})();
  • “this” in arrow function, keeps on referring to the same object it’s referring to outside of the function.
(function () {
  "use strict";

  let incrementer = {
    sum: 0,
    computeSum: function (values) {
      // inner function as arrow function
      values.forEach((value) => (this.sum += value));
    },
  };

  incrementer.computeSum([1, 2, 3]);
  console.log(incrementer.sum);
})();

/*(function () { // error
  "use strict";

  let incrementer = {
    sum: 0,
    computeSum: function (values) {
      //  in strict mode, "this" is undefined in the inner function
      values.forEach(function (value) {
        this.sum += value; //  Cannot read property 'sum' of undefined
      });
    },
  };

  incrementer.computeSum([1, 2, 3]);
  console.log(incrementer.sum);
})();*/