Friday, November 30, 2018

Console.log()

Outputs a message to the Web Console.
Note: This feature is available in Web Workers.

SyntaxSection

console.log(obj1 [, obj2, ..., objN]);
console.log(msg [, subst1, ..., substN]);

ParametersSection

obj1 ... objN
A list of JavaScript objects to output. The string representations of each of these objects are appended together in the order listed and output. Please be warned that if you log objects in the latest versions of Chrome and Firefox what you get logged on the console is a reference to the object, which is not necessarily the 'value' of the object at the moment in time you call console.log(), but it is the value of the object at the moment you click it open.
msg
A JavaScript string containing zero or more substitution strings. 
subst1 ... substN
JavaScript objects with which to replace substitution strings within msg. This gives you additional control over the format of the output.
See Outputting text to the console in the documentation of console for details.

Wednesday, November 28, 2018

A 10 minute primer to JavaScript modules, module formats, module loaders and module bundlers

Modern JavaScript development can be overwhelming.
When working on a project, you may wonder why all the modern machinery and tooling is needed.
What are tools like Webpack and SystemJS doing? Or what do AMD, UMD or CommonJS mean? How do they relate to each other? And why do you need them at all?
In this article you will learn the difference between JavaScript modules, module formats, module loaders and module bundlers.
This not an in-depth guide into any of the individual tools or patterns, but a primer to quickly understand the concepts of modern JavaScript development.
So let's get started.

What is a module?

A module is a reusable piece of code that encapsulates implementation details and exposes a public API so it can be easily loaded and used by other code.

Why do we need modules?

Technically we can write code without modules.
Modules are a pattern that developers have been using in many different forms and programming languages since the 60's and 70's.
In JavaScript, modules should ideally allow us to:
  • abstract code: to delegate functionality to specialised libraries so that we don't have to understand the complexity of their actual implementation
  • encapsulate code: to hide code inside the module if we don't want the code to be changed
  • reuse code: to avoid writing the same code over and over again
  • manage dependencies: to easily change dependencies without rewriting our code

Module patterns in ES5

EcmaScript 5 and earlier editions were not designed with modules in mind. Over time, developers came up with different patterns to simulate modular design in JavaScript.
To give you an idea of what some of these patterns look like, let's quickly look at 2 easy ones: Immediately Invoked Function Expressions and Revealing Module.

Immediately Invoked Function Expression (IIFE)

(function(){
  // ...
})()
An Immediately Invoked Function Expression (IIFE) is an anonymous function that is invoked when it is declared.
Notice how the function is surrounded by parentheses. In JavaScript, a line starting with the word function is considered as a function declaration:
// Function declaration
function(){  
  console.log('test');
}
Immediately invoking a function declaration throws an error:
// Immediately Invoked Function Declaration
function(){  
  console.log('test');
}()

// => Uncaught SyntaxError: Unexpected token )
Putting parentheses around the function makes it a function expression:
// Function expression
(function(){
  console.log('test');
})

// => returns function(){ console.log('test') }
The function expression returns the function, so we can immediately call it:
// Immediately Invoked Function Expression
(function(){
  console.log('test');
})()

// => writes 'test' to the console and returns undefined
Immediately Invoked Function Expressions allow us to:
  • encapsulate code complexity inside IIFE so we don't have to understand what the IIFE code does
  • define variables inside the IIFE so they don't pollute the global scope (varstatements inside the IIFE remain within the IIFE's closure)
but they don't provide a mechanism for dependency management.

Revealing Module pattern

The Revealing Module pattern is similar to an IIFE, but we assign the return value to a variable:
// Expose module as global variable
var singleton = function(){

  // Inner logic
  function sayHello(){
    console.log('Hello');
  }

  // Expose API
  return {
    sayHello: sayHello
  }
}()
Notice that we don't need the surrounding parentheses here because the word functionis not at the beginning of the line.
We can now access the module's API through the variable:
// Access module functionality
singleton.sayHello();  
// => Hello
Instead of a singleton, a module can also expose a constructor function:
// Expose module as global variable
var Module = function(){

  // Inner logic
  function sayHello(){
    console.log('Hello');
  }

  // Expose API
  return {
    sayHello: sayHello
  }
}
Notice how we don't execute the function at declaration time.
Instead, we instantiate a module using the Module constructor function:
var module = new Module();  
to access its public API:
module.sayHello();  
// => Hello
The Revealing Module pattern offers similar benefits as an IIFE, but again does not offer a mechanism for dependency management.
As JavaScript evolved, many more different syntaxes were invented for defining modules, each with their own benefits and downsides.
We call them module formats.

Module formats

A module format is the syntax we can use to define a module.
Before EcmaScript 6 or ES2015, JavaScript did not have an official syntax to define modules. Therefore, smart developers came up with various formats to define modules in JavaScript.
Some of the most widely adapted and well known formats are:
  • Asynchronous Module Definition (AMD)
  • CommonJS
  • Universal Module Definition (UMD)
  • System.register
  • ES6 module format
Let's have a quick look at each one of them so you can recognize their syntax.

Asynchronous Module Definition (AMD)

The AMD format is used in browsers and uses a define function to define modules:
//Calling define with a dependency array and a factory function
define(['dep1', 'dep2'], function (dep1, dep2) {

    //Define the module value by returning a value.
    return function () {};
});

CommonJS format

The CommonJS format is used in Node.js and uses require and module.exports to define dependencies and modules:
var dep1 = require('./dep1');  
var dep2 = require('./dep2');

module.exports = function(){  
  // ...
}

Universal Module Definition (UMD)

The UMD format can be used both in the browser and in Node.js.
(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
      define(['b'], factory);
  } else if (typeof module === 'object' && module.exports) {
    // Node. Does not work with strict CommonJS, but
    // only CommonJS-like environments that support module.exports,
    // like Node.
    module.exports = factory(require('b'));
  } else {
    // Browser globals (root is window)
    root.returnExports = factory(root.b);
  }
}(this, function (b) {
  //use b in some fashion.

  // Just return a value to define the module export.
  // This example returns an object, but the module
  // can return a function as the exported value.
  return {};
}));

System.register

The System.register format was designed to support the ES6 module syntax in ES5:
import { p as q } from './dep';

var s = 'local';

export function func() {  
  return q;
}

export class C {  
}

ES6 module format

As of ES6, JavaScript also supports a native module format.
It uses an export token to export a module's public API:
// lib.js

// Export the function
export function sayHello(){  
  console.log('Hello');
}

// Do not export the function
function somePrivateFunction(){  
  // ...
}
and an import token to import parts that a module exports:
import { sayHello } from './lib';

sayHello();  
// => Hello
We can even give imports an alias using as:
import { sayHello as say } from './lib';

say();  
// => Hello
or load an entire module at once:
import * as lib from './lib';

lib.sayHello();  
// => Hello
The format also supports default exports:
// lib.js

// Export default function
export default function sayHello(){  
  console.log('Hello');
}

// Export non-default function
export function sayGoodbye(){  
  console.log('Goodbye');
}
which you can import like this:
import sayHello, { sayGoodbye } from './lib';

sayHello();  
// => Hello

sayGoodbye();  
// => Goodbye
You can export not only functions, but anything you like:
// lib.js

// Export default function
export default function sayHello(){  
  console.log('Hello');
}

// Export non-default function
export function sayGoodbye(){  
  console.log('Goodbye');
}

// Export simple value
export const apiUrl = '...';

// Export object
export const settings = {  
  debug: true
}
Unfortunately, the native module format is not yet supported by all browsers.
We can already use the ES6 module format today, but we need a transpiler like Babel to transpile our code to an ES5 module format such as AMD or CommonJS before we can actually run our code in the browser.

Module loaders

A module loader interprets and loads a module written in a certain module format.
A module loader runs at runtime:
  • you load the module loader in the browser
  • you tell the module loader which main app file to load
  • the module loader downloads and interprets the main app file
  • the module loader downloads files as needed
If you open the network tab in your browser's developer console, you will see that many files are loaded on demand by the module loader.
A few examples of popular module loaders are:
  • RequireJS: loader for modules in AMD format
  • SystemJS: loader for modules in AMD, CommonJS, UMD or System.register format

Module bundlers

A module bundler replaces a module loader.
But, in contrast to a module loader, a module bundler runs at build time:
  • you run the module bundler to generate a bundle file at build time (e.g. bundle.js)
  • you load the bundle in the browser
If you open the network tab in your browser's developer console, you will see that only 1 file is loaded. No module loader is needed in the browser. All code is included in the bundle.
Examples of popular module bundlers are:
  • Browserify: bundler for CommonJS modules
  • Webpack: bundler for AMD, CommonJS, ES6 modules

Summary

To better understand tooling in modern JavaScript development environments, it is important to understand the differences between modules, module formats, module loaders and module bundlers.
module is a reusable piece of code that encapsulates implementation details and exposes a public API so it can be easily loaded and used by other code.
module format is the syntax we use to define a module. Different module formats such AMDCommonJSUMD and System.register have emerged in the past and a native module format is now available since ES6.
module loader interprets and loads a module written in a certain module format at runtime. Popular examples are RequireJS and SystemJS.
module bundler replaces a module loader and generates a bundle of all code at build time. Popular examples are Browserify and Webpack.
There you have it—you are now armed with the knowledge to better understand modern JavaScript development.
Next time the TypeScript compiler asks you what module format you wish to compile your TypeScript in, you should fully understand why. If you don't, don't worry and just re-read this primer.
Have a wonderful day and develop with passion.

Saturday, November 24, 2018

delete operator

The JavaScript delete operator removes a property from an object; if no more references to the same property are held, it is eventually released automatically.

SyntaxSection

delete expression 
where expression should evaluate to a property reference, e.g.:
delete object.property
delete object['property']

ParametersSection

object
The name of an object, or an expression evaluating to an object.
property
The property to delete.

Return valueSection

true for all cases except when the property is an own non-configurable property, in which case, false is returned in non-strict mode.

ExceptionsSection

Throws Global_objects/SyntaxError in strict mode if the property is an own non-configurable property.

DescriptionSection

Unlike what common belief suggests, the delete operator has nothing to do with directly freeing memory. Memory management is done indirectly via breaking references. See the memory management page for more details.
The delete operator removes a given property from an object. On successful deletion, it will return true, else false will be returned. However, it is important to consider the following scenarios:
  • If the property which you are trying to delete does not exist, delete will not have any effect and will return true
  • If a property with the same name exists on the object's prototype chain, then, after deletion, the object will use the property from the prototype chain (in other words, delete only has an effect on own properties).
  • Any property declared with var cannot be deleted from the global scope or from a function's scope.
    • As such, delete cannot delete any functions in the global scope (whether this is part from a function definition or a function expression).
    • Functions which are part of an object (apart from the global scope) can be deleted with delete.
  • Any property declared with let or const cannot be deleted from the scope within which they were defined.
  • Non-configurable properties cannot be removed. This includes properties of built-in objects like MathArrayObject and properties that are created as non-configurable with methods like Object.defineProperty().
The following snippet gives a simple example:
var Employee = {
  age: 28,
  name: 'abc',
  designation: 'developer'
}

console.log(delete Employee.name);   // returns true
console.log(delete Employee.age);    // returns true

// When trying to delete a property that does 
// not exist, true is returned 
console.log(delete Employee.salary); // returns true

Non-configurable propertiesSection

When a property is marked as non-configurable, delete won't have any effect, and will return false. In strict mode this will raise a SyntaxError.
var Employee = {};
Object.defineProperty(Employee, 'name', {configurable: false});

console.log(delete Employee.name);  // returns false
varlet and const create non-configurable properties that cannot be deleted with the delete operator:
var nameOther = 'XYZ';

// We can access this global property using:
Object.getOwnPropertyDescriptor(window, 'nameOther');  

// output: Object {value: "XYZ", 
//                  writable: true, 
//                  enumerable: true,
//                  configurable: false}

// Since "nameOther" is added using with the
// var keyword, it is marked as "non-configurable"

delete nameOther;   // return false
In strict mode, this would have raised an exception.

Strict vs. non-strict modeSection

When in strict mode, if delete is used on a direct reference to a variable, a function argument or a function name, it will throw a SyntaxError.
Any variable defined with var is marked as non-configurable. In the following example, salary is non-configurable and cannot be deleted. In non-strict mode, the delete operation will return false.
function Employee() { 
  delete salary;
  var salary;
}

Employee();
Let's see how the same code behaves in strict mode. Instead of returning false, the statement raises a SyntaxError.
"use strict";

function Employee() {
  delete salary;  // SyntaxError
  var salary;        
}

// Similarly, any direct access to a function
// with delete will raise a SyntaxError

function DemoFunction() {
  //some code
}

delete DemoFunction; // SyntaxError

ExamplesSection

// Creates the property adminName on the global scope.
adminName = 'xyz';            

// Creates the property empCount on the global scope.
// Since we are using var, this is marked as non-configurable. The same is true of let and const.
var empCount = 43;

EmployeeDetails = {
  name: 'xyz',
  age: 5,
  designation: 'Developer'
};

// adminName is a property of the global scope.
// It can be deleted since it is created without var,
// and is therefore configurable.
delete adminName;       // returns true

// On the contrary, empCount is not configurable
// since var was used.
delete empCount;       // returns false 

// delete can be used to remove properties from objects.
delete EmployeeDetails.name; // returns true 

// Even when the property does not exist, delete returns "true".
delete EmployeeDetails.salary; // returns true 

// delete does not affect built-in static properties.
delete Math.PI; // returns false 

// EmployeeDetails is a property of the global scope.
// Since it was defined without "var", it is marked configurable.
delete EmployeeDetails;   // returns true

function f() {
  var z = 44;

  // delete doesn't affect local variable names
  delete z;     // returns false
}

delete and the prototype chainSection

In the following example, we delete an own property of an object while a property with the same name is available on the prototype chain:
function Foo() {
  this.bar = 10;
}

Foo.prototype.bar = 42;

var foo = new Foo();

// foo.bar is associated with the 
// own property. 
console.log(foo.bar); // 10 

// Delete the own property within the 
// foo object. 
delete foo.bar; // returns true 

// foo.bar is still available in the 
// prototype chain. 
console.log(foo.bar); // 42 

// Delete the property on the prototype.
delete Foo.prototype.bar; // returns true 

// The "bar" property can no longer be 
// inherited from Foo since it has been 
// deleted. 
console.log(foo.bar); // undefined

Deleting array elementsSection

When you delete an array element, the array length is not affected. This holds even if you delete the last element of the array.
When the delete operator removes an array element, that element is no longer in the array. In the following example, trees[3] is removed with delete.
var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
delete trees[3];
if (3 in trees) {
    // this is not executed
}
If you want an array element to exist but have an undefined value, use the undefined value instead of the delete operator. In the following example, trees[3] is assigned the value undefined, but the array element still exists:
var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
trees[3] = undefined;
if (3 in trees) {
    // this is executed
}
If instead, you want to remove an array element by changing the contents of the array, use the splice method. In the following example, trees[3] is removed from the array completely using splice:
var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
trees.splice(3,1);
console.log(trees); // ["redwood", "bay", "cedar", "maple"]