JavaScript Inheritance

JavaScript does not offer classical inheritance structure where child class inherit properties of parent classes. JavaScript allows inheritance between objects with the help of prototype.

JavaScript built-in approach for inheritance is called prototype chaining, or prototypal inheritance. Prototype properties are automatically available on object instances which is a form of ineritance. Because prototype is also an object, it has its own properties and inherits properties from that. This is the prototype chain. An object inherits from its prototype, while that prototype in turn inherits from its prototype, and so on.

All objects inherit from Object. More specifically, all objects inherit from Object.prototype.

var person = {
    name: "shahzad"
};
var prototype = Object.getPrototypeOf(person);
console.log(prototype === Object.prototype);	//returns true

There are five method that appear on all objects through inheritance. They are inherited from Object.prototype;

hasOwnProperty() -> Determines whether an own property with the given name exists
propertyIsEnumerable() -> Determines whether an own property is enumerable
isPrototypeOf() -> Determines whether the object is the prototype of another
valueOf() -> Returns the value representation of the object
toString() -> Returns a string representation of the object

The last two are important when we need to make objects work consistently in JavaScript, and sometime we might want to define them ouself.

valueOf()

This method gets called whenever an operator is used on an object. By default, valueOf() simply returns the object instance. The primitive wrapper types override valueOf() so that it returns and string for String, a Boolean for Boolean and so on.

var now = new Date();
var earlier = new Date(2020,1,1);
console.log(now > earlier)	//returns true

now is the date representing the current time, and earlier is a fixed date in the past. When the greater-than-operator (>) is used, the valueOf() method is called on both objects before the comparison is performed. We can even subtract one date from another and get the difference in epoch time because of valueOf().

We can define our own valueOf() method if our objects are intended to be used with operators. We are not chaning how the operator works, only what value is used with operator’s default behavior.

toString()

The toString() method is called as a fallback whenever valueOf() returns a reference value instead of primitive value. It is also implicitly called on primitive values whenever JavaScript is expecting a string. For example, when a string is used as one operand for the plus operator, the other operand is automatically converted to a string. If the other operand is a primitive value, it is converted into a string representations (for example, true becomes “true”), but if its is reference value, then valueOf() is called.

var person = {
    name: "shahzad"
};
var message = "Name = " + person;	
console.log(message);	//returns Name = [object Object]

The code constructs the string by combining “Name =” with person. Since person is an object, its toString() method is called. The method is inherited from Object.prototype and returns the default value of “[object object]” in most JavaScript engines. If we are not happy with this value, we need to provide our own toString() method implementation.

var person = {
    name: "shahzad",
    toString: function() {
        return "[Name " + this.name + " ]"
    }
};
var message = "Name = " + person;
console.log(message);		//returns Name = [Name shahzad ]

Object Inheritance

The simples type of inheritance is between objects. All we have to do is specify what should be the new object’s [[Prototype]].

When a property is accessed on an object, the JavaScript engine goes through a search process. If the property is found on the instance, that property value is used. If the property is not found on the instance, the search continues on [[Prototype]]. If the property is still not found, the search continues to that object’s [[Prototype]], and so on until the end of the chain is reached. That chain usually ends with Object.prototype, whose [[Prototype]] is set to null.

We can also create objects with a null [[Prototype]] via Object.create();

var nakedObject = Object.create(null);
console.log("toString" in nakedObject);		//returns false
console.log("valueOf" in nakedObject);		//returns false

The naked object is an object with no prototype chain. That means built-in methods such as toString() and valueOf() aren’t present on the object. This object is a completely blank slate with no predefined properties, which makes it perfect for creating a lookup hash without potential naming collisions with inherited property names. There aren’t many other uses for an object like this. For example, any time you use an operator on this object, you’ll get an error “Cannot convert object to primitive value.”.

Constructor Inheritance

Object inheritance is the basis of constructor inheritance. Every function has a prototype property that can be modified or replaced. The property is automatically assigned to be a new generic object and has single own property called constructor. In effect, the JavaScript engine does the following for you;

//your write this
function MyConstructor(){
	//initialization
}

//JavaScript engine does this for you behind the scenes
MyConstructor.prototype = 
Object.create(Object.prototype, {
	constructor: {
		configurable: true,
		enumerable: true,
		value: MyConstructor,
		writable: true
}
});

MyConstructor is a subtype of Object, and Object is a supertype of MyConstructor. Prototype property is writable, we can change the prototype chain by overwriting it.

//first constructor
function Rectangle(length, width){
    this.length = length;
    this.width = width;
};

Rectangle.prototype.getArea = function() {
    return this.length * this.width;
};

Rectangle.prototype.toString = function() {
    return "[Rectangle " + this.length + " X " + this.width + "]";
};

//inherits from Rectangle
//second constructor
function Square(size) {
    this.length = size;
    this.width = size;
};

Square.prototype = new Rectangle();
Square.prototype.constructor = Square;

Square.prototype.toString = function() {
    return "[Square " + this.length + " x " + this.width + "]";
};

var rect = new Rectangle(5,10);
var square = new Square(6);
console.log(rect.getArea());	//returns 50
console.log(square.getArea());	//returns 36
console.log(rect.toString());	//returns [Rectangle 5 X 10]
console.log(square.toString());	//returns [Square 6 x 6]
console.log(rect instanceof Rectangle);	//returns true
console.log(rect instanceof Object);	//returns true
console.log(square instanceof Square);	//returns true
console.log(square instanceof Rectangle);	//returns true
console.log(square instanceof Object);	//returns true

In the above code, there are two constructors: Rectangle and Square. The Square constructor has it prototype property overwritten with an instance of Rectangle. No arguments are passed into Rectangle at this point because they don’t need to be used, and if they were, all instances of Square would share the same dimensions. The constructor property is restored on Square.prototype after the original value is overwritten.

rect is created as an instance of Rectangle, and square is created an an instance of Square. Both objects have the getArea() method because it is inherited from Rectangle.prototype. The square variable is considered as instance of Square as well as Rectangle and Object because instanceof uses the prototype chain to determine the object type.

Square.prototype doesn’t actually need to be overwritten. Rectangle constructor isn’t doing anything that is necessary for Square. The only relevant part is that Square.prototype needs to somehow link to Rectangle.prototype in order for inheritance to happen. That means, we can simplify the example by using Object.create();

//inherits from Rectangle
function Square(size) {
    this.length = size;
    this.width = size;
};
Square.prototype = Object.create(Rectangle.prototype, {
    constructor: {
        configurable: true,
        enumerable: true,
        value: Square,
        writable: true
    }
});
Square.prototype.toString = function() {
    return "[Square " + this.length + " x " + this.width + "]";
};
var square = new Square(5)
console.log(square.getArea());		//returns 25
console.log(square instanceof Square);	//returns true
console.log(square instanceof Rectangle);	//returns true
console.log(square instanceof Object);	//returns true
console.log(square.toString());		//returns [Square 5 x 5]

In this version, Square.prototype is overwritten with a new object that inherits from Rectangle.prototype, and the Rectangle constructor is never called. That means we don’t need to worry about causing an error by calling the constructor without arguments anymore.

Always make sure that you overwrite the prototype before adding properties to it, or you will lose the added methods when the overwrite happens.

Accessing Supertype (Base) Methods

In our previous example, the Square type has its own toString() method that shadown toString() on the prototype. What if we want to use base type method? JavaScript allows you to directly access the method on the supertype’s prototype and use either call() or apply() to execute the method.

Replace this;

Square.prototype.toString = function() {
    return "[Square " + this.length + " x " + this.width + "]";
};

With this;

Square.prototype.toString = function() {
    var text = Rectangle.prototype.toString.call(this);
    return text.replace("Rectangle", "Square");
};
var square = new Square(5)
console.log(square.getArea());	//returns 25
console.log(square.toString());	//returns [Square 5 X 5]

JavaScript Constructors and Prototypes

JavaScript lack classes, it turns to constructors and prototype to bring a similar order to objects.

Constructors

A constructor is simply a function that is used with new to create an object. There are built-in constructors for Object, Array and Functions. The advantage of constructors is that objects created with the same constructor contains the same properties and methods.

The constructor names should begin with capital letter, to distinguish them from other functions.

function Person() {
    //intentionally empty
}

This function is a constructor. The clue that Person is a constructor is in the name – the first letter is capitalized. Let’s create some instances;

var person1 = new Person();
var person2 = new Person();

The new operator automatically creates an object of the given type and returns it. We can use the instanceof operator to confirm object’s type.

console.log(person1 instanceof Person)		//returns true
console.log(person2 instanceof Person)		//returns true

We can also check the type of an instance using the constructor property. For generic objects (those created via an object literal or the object constructor), constructor is set to Object. For objects created with a custom constructor, constructor points back to that constructor function, in our case Person.

console.log(person1.constructor === Person);	//returns true
console.log(person2.constructor === Person);	//returns true

Let’s add some properties inside constructor;

function Person(name){
    this.name = name;
    this.sayName = function()
    {
        console.log(this.name);
    };
}

Now we can use the Person constructor to create objects with an initialized name property;

var person1 = new Person("shahzad");
var person2 = new Person("ali");
console.log(person1.name);		//returns shahzad
console.log(person2.name);		//returns ali

person1.sayName();			//returns shahzad
person2.sayName();			//returns ali

Make sure to always call constructors with new; otherwise it will be created on global objects. Constructors don’t eliminate code redundancy. For example, each instance has its own sayName() method even though sayName() doesn’t change. What if we have 100 instances of an object, then there are 100 copies of a function that do the exact same thing, just with different data.

If would be much more efficient if all of the instances shared one method, and then that method could use this.name to retrieve the appropriate data. This is where prototypes come in.

Prototypes

Think of prototype as a recipe for an object. Almost every function (except some built-in functions) has a prototype property that is used during the creation of new instances. This property is shared among all of the object instances. For example, hasOwnProperty() method is defined on generic Object prototype, but it can be accessed from any objects.

function Person(name){
    this.name = name;
}

Person.prototype.sayName = function() {
    console.log(this.name);
};

var p = new Person("shahzad");
var p1 = new Person("ali");

console.log(person1.name)	//returns "shahzad"
console.log(person2.name)	//returns "ali"
person1.sayName();		//returns “shahzad”
person2.sayName();		//returns “ali”

Let’s assign constructor property specifically on the prototype;

Person.prototype = {
    constructor: Person,
    
    sayName: function() {
        console.log(this.name);
    },
    
    toString: function() {
        return "[Person " + this.name + "]";
    }
};

var person1 = new Person("shahzad");
var person2 = new Person("ali");
console.log(person1 instanceof Person);		//returns true
console.log(person1.constructor === Person);	//returns true
console.log(person1.constructor === Object);	//returns false
console.log(person2 instanceof Person);		//returns true
console.log(person2.constructor === Person);	//returns true
console.log(person2.constructor === Object);	//returns false

JavaScript Objects

JavaScript Objects can be created using object constructor and object literal;

Using Object literal

var person1 = {
    name: "shahzad"
};
person1.age = 34;
person1		//returns  {name: "shahzad", age: 34}

using Object constructor

var person2 = new Object();
person2.name = "shahzad"
person2.age = 34
person2		//returns  {name: "shahzad", age: 34}

JavaScript uses an internal method called [[Put]] to add a property to object. We can compare this to adding a key to a hash table for the first time. Internally JavaScript engine makes a [[Put]] call that results in the creation of an own property on the object. This means that the specific instance of the object owns that property. All operations on the property must be performed through that object.

When a new value is assigned to existing property, a separate operation called [[Set]] happens. Thee operation results in replacing current property value with a new one.

Detecting Properties

Properties can be added dynamically. If we want to check the existence of a property;

if (person1.age){
    console.log("property exists")		//returns “property exists“
}

This method of checking property works but it is not reliable. The if condition evaluates to true if the value is truthy (an object, a nonempty string, a nonzero number, or true) and false if the value is falsy (null, undefined, 0, false, NaN, or an empty string). In the example code, the object property can contain one of these falsy value and will return false negatives.

Let’s test this;

person1.age = 0
if (person1.age){
    console.log("property exists")		//returns false negative value “Undefined”
}

A more reliable way to test the existence of a property is with “in” operator.

console.log("name" in person1);	//returns true
console.log("age" in person1);		//returns true
console.log("title" in person1);		//returns false

The “in” operator looks for a property in an object and returns true if exists otherwise false. We can also check the existence of a method using “in” operator.

var person = {
    name: "shahzad",
    sayName: function(){
        console.log(this.name);
    }
};
console.log("sayName" in person);	//returns true

The “in” operator added benefit is to not evaluating the value of the property which affects function performance overall.

What If we want to check existence of a property only if it is an own property.

The “in” operator checks for own properties and prototype properties.

console.log("name" in person);		//returns true
console.log("toString" in person);	//returns true

The hasOwnProperty() method checks the presence of an own property in the object.

console.log(person.hasOwnProperty("name"));		//returns true
console.log(person.hasOwnProperty("toString"));	//returns false

Removing Properties

Setting a property to null doesn’t actually remove the property completely. The will make an operation call [[Set]] with a value of null. We need to use the delete operator to completely remove a property from an object. The delete operator works on a single object property. We can think of this operation as removing a key/value pair from hash table.

When delete operation is successful, it returns true;

var person = {
    name: "shahzad"
};
console.log(person)		//returns {name: "shahzad"}
console.log("name" in person)	//returns true
delete person.name		//returns true – no output
console.log("name" in person)	//returns false
console.log(person.name)	//returns undefined

Object Enumeration

All properties we add to an object are enumerable by default. We can iterate over them using for-in loop. Enumerable properties have their internal [[Enumerable]] attribute set to true. The for-in loop enumerates all enumerable properties on an object, assigning the property name to a variable.

//define object
var person1 = {
    name: "shahzad",
    age: 34
};

//enumerate this object
var property;
for (property in person1) {
    console.log("Name: " + property);
    console.log("Value: " + person1[property]);
}

//return values
Name: name
Value: shahzad
Name: age
Value: 34

If we just want to need a list of an object’s properties to use later in the program, ECMAScript 5 introduced the Object.keys() method. This retrieves an array of enumerable property names;

var properties = Object.keys(person1);
var i, len;
for (i=0,len=properties.length;i<len;i++){
    console.log("Name: " + properties[i]);
    console.log("Value: " + person1[properties[i]]);
}
//return values
Name: name
Value: shahzad
Name: age
Value: 34

The for-in-loop and Object.keys() behaves similar but there is a difference in underlying behavior. The for-in-loop enumerates own (instance) properties and prototype properties. Object.keys() returns only own (instances) properties.

Not all properties are enumerable. Most of the native methods on object have their [[Ienumerable]] attribute set to false. To check if a property is enumerable or not, use this;

Check with propertyIsEnumberable

console.log("name" in person1)		//returns true
console.log(person1.propertyIsEnumerable("name"));	//returns true

Check with Object.Keys

var properties = Object.keys(person1)
console.log("length" in properties)	//returns true – native property
console.log(properties.propertyIsEnumerable("length"));	//returns false

Types of properties

JavaScript has data properties and accessor properties. Data properties contain a value, like the name property from earlier example. The default behavior of the [[Put]] method is to create a data property.

Accessor properties don’t contain a value but instead define a function to call when the property is read (called a getter), and a function to call when the property is written to (called a setter). Accessor properties only required either a getter or a setter, though they can have both.

var person = {
    _name: "shahzad",
    
    get name() {
        console.log("readming name");
        return this._name;
    },
    set name(value) {
        console.log("setting name to %s", value);
        this._name = value;
    }
};
console.log(person.name) 	//returns “readming name” then “shahzad”
person.name = "Ali";		//returns “setting name to Ali” then “Ali”

This example defines an accessor property called name. There is a data property called _name that contains the actual value for the property. The leading underscore is a common convention to indicate that property is considered to be private, though in reality it is still public.

The syntax for getter and setter looks a lot like function without function keyword. The special keyword get and set are used before accessor property name.

Property Attributes

Prior to ECMAScript 5, there was no way to access the internal attributes of a property at all. ECMAScript 5 changed this by introducing several ways of interacting with property attributes directly as well as introducing new attributes. It’s now possible to create properties that behave the same way as built-in JavaScript properties.

Common attributes

There are two property attributes shared between data and accessor properties. One is [[Enumerable]] which determines whether we can iterated over the property, and second is [[Configurable]] which determines whether the property can be changed. By default all properties on an object are both enumerable and configurable.

Object.defineProperty() method is used to change property attributes.

var person1 = {
    name: "shahzad"
};

Object.defineProperty(person1, "name", {
    enumerable: false
});

console.log("name" in person1);	//returns true
console.log(person1.propertyIsEnumerable("name"));	//returns false

This is alternative method for doing the same thing;

var properties = Object.keys(person1);
console.log(properties.length);		//returns 0
Object.defineProperty(person1,"name",{
    configurable:false
});
delete person1.name			//try to delete the property, returns false
console.log("name" in person1);	//return true

Data Property Attributes

There are two additional attributes in data property that accessor do not. The first is [[Value]], which holds the property value. This attribute is filled in automatically when we create a property on an object. The second is [[Writable]], which is Boolean value indicating whether the property can be written to. By default, all properties are writable unless we specify otherwise.

With these two additional attributes, we can define a data property using Object.defineProperty() even if the property does not already exist.

var person1 = {};
Object.defineProperty(person1, "name", {
    value: "shahzad",
    enumerable: true,
    configurable: true,
    writable: true
});

Object.defineProperty() will first check to see if the property exists, if it doesn’t it will create a new one. It is important to specify all the attributes because Boolean attributes default to false. For example;

Object.defineProperty(person1, "name", {
    value: "shahzad",
});

enumberalbe, configurable and writable will be automatically false.

Accessor Property Attributes

There are two additional attributes, [[Get]] and [[Set]]. There is no value stored for getters/setters so there is no need for [[Value]] or [[Writable]] attributes.

Defining Multiple Properties

We can define multiple properties, If we use Object.defineProperties() instead of Object.defineProperty().

var person = {};
Object.defineProperties(person, {
    _name: {
        value: "shahzad",
        enumerable:true,
        configurable:true,
        writable: true
    },
    //accessor property
    name: {
        get: function() {
            console.log("reading name");
            return this._name;
        },
        set: function(valule) {
            console.log("Setting name to %s", value);
            this._name = value;
        },
        enumerable: true,
        configurable: true
    }
});        

Retrieving Property Attributes

Object.getOwnPropertyDescriptor() can be used to fetch property attributes. This method works only on own properties. For example, this code create a property and check its attributes;

var person = {
    name: "shahzad"
};
var descriptor = Object.getOwnPropertyDescriptor(person, "name");

console.log(descriptor.enumerable);	//returns true
console.log(descriptor.configurable);	//returns true
console.log(descriptor.writable);	//returns true
console.log(descriptor.value);		//returns “shahzad”

Preventing Object Modification

[[Extensible]] attribute is a Boolean value indicating if the object can be modified. By default all objects are extensible, meaning new properties can be added.

To prevent extension, first method is to use Object.preventExtensions().

var person = {
    name: "shahzad"
};
console.log(Object.isExtensible(person));	//returns true
Object.preventExtensions(person);		//prevent extension
console.log(Object.isExtensible(person));	//returns false
//modify object
person.sayName = function(){
    console.log(this.name);
};
console.log("sayName" in person);		//return false, object is not modified

Attempting to add a property/method to a nonextensible object will throw an error in strict mode. In nonrestrict mode, the operation fails silently.

To prevent extension, second method is to use Object.seal().

var person = {
    name: "shahzad"
};
console.log(Object.isExtensible(person));	//returns true
console.log(Object.isSealed(person));		//returns false
Object.seal(person)				//Seal the object
console.log(Object.isExtensible(person));	//returns false
console.log(Object.isSealed(person));		//returns true
//try to modify object
person.sayName = function(){
    console.log(this.name);
};
console.log("sayName" in person);		//returns false
person.name = "Ali";
console.log(person.name);			//returns “Ali”
delete person.name;				//returns false
console.log("name" in person);			//returns true
console.log(person.name);			//returns “Ali”
var descriptor = 
    Object.getOwnPropertyDescriptor(person, "name");
console.log(descriptor.configurable);		//returns false

Be sure to use strict mode with sealed objects so we’ll get an error when someone tries to use the object incorrectly.

The last way to create a nonextensible object is to freeze it. In essence, a frozen object is a sealed object where data properties are also read-only. Frozen objects can not become unfrozen so they remain in the state when they become frozen. We can use Object.freeze() to freeze an object and Object.isFrozen() to determine if an object is frozen.

var person = {
    name: "shahzad"
};
console.log(Object.isExtensible(person));	//returns true
console.log(Object.isSealed(person));		//returns false
console.log(Object.isFrozen(person));		//returns false
Object.freeze(person);				//freeze object, data properties becomes read-only
console.log(Object.isExtensible(person));	//returns false
console.log(Object.isSealed(person));		//returns true
console.log(Object.isFrozen(person));		//returns true
//try to modify object
person.sayName = function(){
    console.log(this.name);
};
console.log("SayName" in person);		//returns false
person.name = "Ali";
console.log(person.name);			//returns shahzad
delete person.name;				//returns false
console.log("name" in person);			//returns true
console.log(person.name);			//returns shahzad
var descriptor = 
    Object.getOwnPropertyDescriptor(person, "name");
console.log(descriptor.configurable);		//returns false
console.log(descriptor.writable);		//returns false

JavaScript Functions

The functions have an internal property names [[Call]]. This property is unique to functions and indicate that the object can be executed. Just because of this property the typeof operator returns type as “function”. In the past different browsers were identifying multiple reference types, for example regular expression, as function that has been corrected now.

Functions can be declared in two different forms;

The first form is function declaration where the function has a name;

function add(num1, num2){
return num1 + num2;
}

The second form is function expression where the function has no name;

var add = function(num1, num2){
return num1 + num2;
};

This code actually assigns a function value to the variable add. The function expression is almost identical to function declaration except for the missing name and the semicolon at the end.

These two forms are similar but there is a difference. Function declarations are hoisted to the top of the context when the code executes. This code might look like it will cause an error, but it works;

var result = add(5,5);		//return 10
function add(num1, num2){
return num1 + num2;
}

The reason, JavaScript engine hoists the function declaration to the top and actually executes the code as if it were written like this;

function add(num1, num2){
return num1 + num2;
}
var result = add(5,5);		//return 10

Function hoisting happens only for function declaration because function name is known ahead of time. This is not true for function expressions.

var result = add(5,5);		//return error
var add = function(num1, num2){
return num1 + num2;
};

If we always define functions before using it, both approaches will work.

Passing Parameters

JavaScript functions allows you to pass any number of parameters to a function without causing any error. The reason, function parameters are stored an array-like structure called arguments. Arguments are similar to JavaScript array. The arguments values are referenced via numeric indices and there is a length property to determine how many values are present.

The argument object is automatically available inside any function. This means names parameters in a function exists mostly for convenience and don’t exactly limit the number of arguments that a function can accept. Function won’t throw an error if we pass too many or too few parameters.

Here is an example;

function reflect(value) {
return value;
}
console.log("hi");		//returns “hi”
console.log("hi", "there");	//returns “hi there”
reflect.length			//returns 0

The same function can be written as;

reflect = function(){
return argument[0];
};
console.og("hi", "there");	//returns “hi”
console.log("hi", "there");	//returns “hi there”
console.log(reflect.length)	//returns 0

The first implementation is much easier to understand because of named argument. The second implementation is using arguments and we much read the body to understand how arguments are used.

The best practice is to use named argument. However, using arguments is actually more effective in case we want to create a function that accepts any number of parameters and return their sum.

function sum()
{
    var result = 0;
    i = 0;
    len = arguments.length;
    
    while (i < len) {
        result += arguments[i];
        i++;
    }
    return result;
}

console.log(sum(1,2)); 			//returns 3
console.log(sum(1,2,3,4,5));		//returns 15
console.log(sum(1,2,3,4,5, 6, 7 , 8));	//returns 36
console.log(sum());			//returns 0
console.log(sum(50));			//returns 50

Function overloading

There is no concept of function overloading in JavaScript. JavaScript function can accept any number of parameters.

function sayMessage(message) {
    console.log(message);
}

Overloading this function;

function sayMessage() {
    console.log("Default message");
}
sayMessage(“Hello”)			//returns “Default message”

Why do we see “Default message” where it should be “Hello”. When we define multiple functions with the same name, the one that appear last in code wins.

We can mimic overloading functionality using this approach;

function sayMessage(message) {
    if (arguments.length == 0) {
    	console.log("Default message");
    }
console.log(message);
}
sayMessage("hi")		//returns “hi”
sayMessage()			//returns “Default message”

Object Methods

Properties can be added or removed from objects at any time. When a property value is function, it’s considered a method.

var person = {
    name:"Shahzad",
    sayName: function(){
        console.log(person.name);
    }
};
person.sayName()		//returns “Shahzad”

Syntax for data property and method is exactly the same. An identifier followed by : and the value. For function the value would be function().

The “this” Object

In our previous example, sayName() method reference person.name directly, which creates tight coupling between the method and the object. If we change the variable name, we also need to remember to change the reference to that name in method. Second, it would be difficult to use the same function for different objects.

Every scope in JavaScript has a “this” object that represents the calling object for the function. In the global scope, this represents the global object (window in web browsers). When a function is called while attached to an object, the value of “this” is equal to that object by default.

Let’s re-write the code;

var person = {
    name:"Shahzad",
    sayName: function(){
        console.log(this.name);
    }
};
person.sayName()		//returns “Shahzad”

This code works the same as the earlier version, but this time, sayName() references “this” instead of person.

Let’s go with another example. Create a function “sayName”. Create two object literals and assign sayName to the sayNameFor function. Functions are reference values so they can be assign as property values on any number of objects.

Define a global variable called name. When sayNameForAll() is called directly, it will output global variable value.

function sayNameForAll() {
    console.log(this.name);
}

var person1 = {
    name: "Shahzad",
    sayName: sayNameForAll
};

var person2 = {
    name: "Ali",
    sayName: sayNameForAll
};

person1.sayName()		//returns “Shahzad“
person2.sayName()		//returns “Ali”
sayNameForAll();		//returns empty value

Why sayNameForAll() returns null because there is no global scope variable. Let’s define one;

var name = “Hamza”;
sayNameForAll();		//returns “Hamza”

Changing this

The ability to use and manipulate the “this” value of functions is key to good object-oriented programming in JavaScript. There are three function method that allow us to change the value of this. Functions are objects and objects have methods, so function can, too.

The call() Method

This execute the function with a particular this value and with specific parameters. Let’s take our earlier example;

function sayNameForAll(label) {
    console.log(label + ":" + this.name);
}

var person1 = {
    name: "Shahzad"    
};

var person2 = {
    name: "Ali"
};

var name = “hamza”;

sayNameForAll.call(this, "global");		//returns global:hamza
sayNameForAll.call(person1, "person1");	//returns person1:Shahzad
sayNameForAll.call(person2, "person2");	//returns person2:Ali

sayNameForAll() accepts one parameter that is used as a label to the output value. There are no parentheses after the function name because it is accessed as an object rather than as code to execute. We did not added the function directly on each object. We explicitly specify the value of this instead of letting the JavaScript engine do it automatically.

The apply() Method

The second method we can use to manipulate “this” is apply(). This method works exactly the same as call() except that it accepts only two parameters: the value for this and an array or array-like object of parameters (it means we can use an arguments object as the second parameter). We can call our methods like this;

sayNameForAll.apply(this,["global"]);		//return global:hamza
sayNameForAll.apply(person1,["person1"]);	//return person1:Shahzad
sayNameForAll.apply(person2,["person2"]);	//return person2:Ali

The use case between call and apply; if we have an array of data, we will use apply(). If we just have individual variable, we will use call().

The bind() Method

This method was added in ECMAScript 5 and it behaves quite differently than the other two. The first argument to bind() is the “this” value for the new function. All other arguments represent named parameters that should be permanently set in the new function.

We can call our methods like this;

var sayNameForPerson1 = sayNameForAll.bind(person1);
sayNameForPerson1("person1");	//returns “person1:Shahzad”

var sayNameForPerson2 = sayNameForAll.bind(person2);	
sayNameForPerson2("person2");	//return “person2:Ali”

Resources

6 Ways to Declare javaScript Function

JavaScript Default Parameters

JavaScript Reference types

Reference types represent objects in JavaScript. They are the closet things to classes. Reference values are instances of reference types.

An object is an unordered list of properties consisting of a name (always a string) and a value. When the value of a property is function, it is called a method.

It helps to think of JavaScript objects as nothing more than hash tables;

—–object——-

|name|value|

|name|value|

Objects can be created using the new operator with a constructor. A constructor is simply a function uses new to create an object. By convention, constructors in JavaScript begin with a capital letter to distinguish them from non-constructor functions. For example;

var object = new Object();

Reference types don’t store the object directly into the variable. It holds a pointer to the location in memory where the object exists. This is the primary difference between objects and primitive values. When you assign one variable to another, each variable gets a copy of the pointer and both reference the same object in memory.

var object = new Object();
var object1 = object;

—-Variable Object—-                                   Memory

|object|——|————->                Pointer1

|object1|—-|————–>                Pointer1

JavaScript is a garbage-collected language, so we don’t need to worry about memory allocations when using reference types. However, the best practice is to deference objects that are no longer required so that garbage collector can free up that memory. The best way to do so;

var object1 = new Object();
//do something
object1 = null;		//dereference

You can add or remove properties from objects; for example;

var object = new Object();
var object1 = object;
object.customProperty = “Awesome!”;
console.log(object1.customProperty);	//returns “Awesome”

The property that’s added to object variable is accessible on object1. The reason, same pointer.

Object type is one of a handful built-in reference types that JavaScript provides. The other builtin types are;

Array =  An ordered list of numerically indexed values

Date = A date and time

Error = A runtime error

Function = A function

Object = A generic object

RegExp = A regular expression

Each of these built-in reference types can be instantiated using new;

var items = new Array()
var now = new Date()
var error = new Error("something bad happend")
var func = new Function("console.log('hi');")
var object = new Object();
var re = new RegExp("\\d+");

Several built-in reference types have literal forms. A literal is a syntax that allow us to define a reference value without explicitly creating an object, using the new keyword.

Object literal

To create an object, we define the properties of new object inside braces. For example;

var book = {
name: "My favorite book",
year: 2014
};

Another format for creating the object if there are spaces in properties;

var book = {
"name": "My favorite book",
"publish year": 2014
};

When using object literal, the JavaScript engine implicitly creates a new Object(). This is true for all reference literals.

Array literal

Array literal can be defined in a similar way;

var colors = ["red","green","blue"]
console.log(colors[0])

This code is equivalent to the following;

var colors = new Array("red","green","blue")
console.log(colors[0])

Function literal

The best approach is to define functions using their literal form. Creating functions is much easier and less error prone using this literal form;

function reflect(value) {
return value;
}

We can create same function using function constructor;

var reflect = new Function("value", "return value;");

Using function constructor is typically discouraged given the challenges of maintaining, reading and debugging a string of code rather than actual code. There is no good way to debug these functions because these are not recognized by JavaScript debuggers. They are like a black box in your application.

Regular Expression literals

Regular expression literal form is;

var numbers = /\d+ /g;

Constructor equivalent is;

var numbers = new RegExp(“\\d+”, “g”);

When using RegExp constructor, patterns are passed as string. Any back-slashes need to be escaped. That’s why \d is used in literal and \\d is used in the constructor above.

Regular expression literals are preferred over the constructor form except when regular expression is being constructed dynamically from one or more strings.

Functions as an exception, there is no right or wrong way to instantiate built-in types.

Property Access

Properties are name/value pairs that are stored on an object. Properties can be accessed by dot notation or bracket notation with a string;

with dot notation;

var array = [];
array.push(12345);

with bracket notation the name of the method is enclosed in square brackets;

var array = [];
array["push"](12345)

This syntax is useful when we want to dynamically decide which property to access. For example, bracket notation allows us to use a variable instead of the string literal to specify the property to access;

var array = [];
var method = "push";
array[method](12345)

bracket notation allows you to use special characters in the property names. dot notation is easier to read and can be seen more frequently in applications.

How to identify reference types

The easiest reference type to identify is function type. Typeof operator on a function should return its type “function”.

function reflect(value) {
return value;
}
console.log(typeof reflect);		//returns “function”

On all other reference types, typeof operator returns “object”. This is not helpful. To solve this, there is another JavaScript operator, instanceof. This operator takes an object and a constructor as parameters. When the value is an instance of the type that constructor specifies, instanceof return true; otherwise, returns false.

var items = [];
var object = {}
function reflect(value) {
return value;
}
console.log(items instanceof Array);		//true
console.log(object instanceof Object);		//true
console.log(reflect instanceof Function);		//true

Every object is actually an instance of an Object because every reference type inherits from Object. The instanceof operator can identify inherited types.

console.log(items instanceof Array);		//true
console.log(items instanceof Object);		//true
console.log(object instanceof Object);		//true
console.log(object instanceof Array);		//false
console.log(reflect instanceof Function);		//true
console.log(reflect instanceof Object);		//true

How to Identify Arrays (Special Case)

Instanceof operator can identify arrays. There is an exception though. JavaScript values are passed back and forth between frames in the same web page. Each web page has its own global context i.e. its own version of Object, Array and all other built-in types. As a result, when we pass an array from one frame to another, instanceof doesn’t work because the array is actually an instance of Array from a different frame.

ECMAScript 5 introduced Array.isArray() that solves this problem.It identifies the value as an instance of Array regardless of the value’s origin.

var items = [];
console.log(Array.isArray(items));	//returns true

The Array.isArray() method is supported in most browser and in Node.js. This method doesn’t support IE 8 and earlier.