If you have been into JS for quite a few time now, you might sometimes wonder that where do the javascript native properties and methods like ‘toString‘, ‘addEventListener‘ and such others come from? Many of you would argue that it is language’s built-in functionality, why should we even care for that? That argument would have been very right if we were not dealing with JS. You can manipulate the javascript native properties(not all) and even add your ones having native-like behaviour. To understand where do they come from, let’s have a quick review of how objects in JS work.

 

Object Delegation

In Javascript, objects inherit from the objects. By default, all the objects inherit from a built-in object Object.prototype‘ but can be made to inherit from any object using a special (linking) property “__proto__“. The reference (to some object) that “__proto__” property of any object contains is called ‘prototype object’ or simply ‘prototype’ of that object.

 

While accessing a property on an object (say X), the engine first checks if that property is present on that particular object(X), if not, it’s(X’s) ‘prototype object'(say Y) is looked for the same property. If this ‘prototype object’ too doesn’t contain the queried property, further the ‘prototype object’ of Y is checked. This lookup takes place until the property is finally found (or if not found after having been searched up to the root of the ‘prototype-chain’ i.e. up to ‘Object.prototype’, undefined is returned).

var foo= {
  name: "js"
}

console.log(foo.__proto__) //Object.prototype
console.log(Object.prototype__proto__) //null (end of chain)
Object.prototype.bar= "bar in the root";
console.log(foo.bar) //"bar in the root"
console.log(foo.name) //"js"

var baz= {
  type: "baz"
}

foo.__proto__ = baz;
console.log(foo.type) // "baz"
console.log(foo.bar) // "bar in the root"

 

In the example above, foo’s prototype by default is ‘Object.prototype. We add ‘bar’ property to ‘Object.prototype’ and notice that we can access it through foo. Then we change foo’s prototype to newly created object ‘baz’ having an own property ‘type’. We now try to access this ‘type’ property of ‘baz’ through ‘foo’ and succeed. Also, we succeed in accessing ‘bar’ (own property of Object.prototype) through ‘foo‘ again. Let us see how ‘bar’ property is resolved (the second time).

 

The Engine: Hey foo, the user wants to access ‘bar’ property from you. Do you have it?
foo: No, I don’t!
The Engine: Well, lemme check your prototype(baz)…baz, do you have any property named ‘bar’?
Baz: No chance. I don’t have it.
The Engine: OK let me go one more step up..to your prototype….. Object.prototype, have you got ‘bar’ ?
Object.prototype: Yep! It’s all here.
The Engine: OK! I am resolving it to the user.

 

Final prototype chain of foo looks something like this- foo>>baz>>Object.prototype.

 

The above is not ideal but the approximate process of how a property is searched through a prototype chain. Always remember, look-up for a property starts from the object it’s accessed on and goes up through the prototypes until it is found or until the chain ends.

//Our basic object

var langs= {
  name: "Languages",
  type: "Web Technology",
  getDetails: function() {
    for(var key in this) {
      if(typeof this[key]!== "function") {
        console.log(key + ": " + this[key]);
      }
    }
  }
};

var JS= {
  name: "JavaScript"
}

JS.name; //JavaScript
JS.type; //undefined
JS.getDetails(); //undefined
langs.name; //Languages
langs.type; //Web Technology

//set prototype of JS to langs
JS.__proto__ = langs;
JS.name; //JavaScript
JS.type; //Web Technology

JS.getDetails(); 
//name: JavaScript
//type: Web Technology

 

In the code above, Object ‘langs‘ has three own-properties- ‘name’, ‘type’ and ‘getDetails’ (as this is a function, we refer to this property as being ‘method’). For the first time when we access name, type and getDetails through JS, we succeed only with name property as others namely ‘type’ and ‘getDetails’ aren’t present in this Object.

 

However, after setting our Object ‘JS’ a property named ‘__proto__’ pointing to ‘langs’ Object, we are able to access langs’ properties through JS object. This is possible because when we set __proto__ with value ‘langs’ to our Object ‘JS’, ‘langs’ becomes prototype of ‘JS’ and when we access type and getDetails property on ‘JS’, it can’t be found in ‘JS’ itself so it’s prototype ‘langs’ is consulted which actually contains these queried properties so resolves them. If any of the queried properties were not present in here too, a prototype of the prototype (with respect to ‘JS’) i.e. prototype of ‘langs’ which is by default set to Object.prototype (last object in prototype-chain) would have been consulted.

 

So Where Do They Come From?

The answer to this question lies within the prototype-chain we discussed above and the fact that almost everything is JS is an Object. Arrays, Strings, Numbers and even Functions( with extra callable functionality) are all objects.

var text= new String("JavaScript");
console.log(text)
console.log(typeof text) // "object"

 

This image is what is what you see when you log you ‘text’ variable in console-

console 1 - Where do javascript native properties come from

Actually, this is why you can do-

console.log(text[0]) //J
console.log(text[1]) //A

 

Now if text is an Object it should have a prototype object, let’s go and check-

console.log(text.__proto__)

 

console 2 - Where do Javascript native properties come from

Whoa! It does have a prototype named ‘String.prototype‘ (not ‘String’).
(Note: you might confuse ‘String.prototype’ with ‘String’ here. Actually, the way in the above image is how ‘String.prototype’ is displayed in the console).

 

Now if text has a prototype it must be able to access all the properties it’s prototype ‘String.prototype’ has. Let’s try

console.log(text.toUpperCase()); //JAVASCRIPT
console.log(text.split("")); // ["J", "a", "v", "a", "S", "c", "r", "i", "p", "t"]

 

Well, things look clear now. But wait using constructor is not how we always initialize the strings, numbers or any data type. We, more than often, prefer primitives(not objects, simple values with no properties)

var text= "JavaScript";
console.log(typeof text) // "string"

 

Now the text is not an object. But you can see below it can still access String.prototype’s properties-

text.toUpperCase(); //JAVASCRIPT

 

How was text able to access properties like toUpperCase, split etc. which are locally found in String.prototype which is not a prototype of text this time(of course! as the text is no more an object now so there is no question of it having a prototype). This is actually possible because primitives become the object for an instant while accessing properties like ‘toUpperCase’. After the execution is finished, they get converted into primitives again.
I promised that native properties and methods can be manipulated. Yes, let’s see how-

 

Natively, toUpperCase method is designed to convert a string to uppercase format but what if we change its value-

String.prototype.toUpperCase= function() {
return this[0];
};

 

We replaced the native function which converted a string into uppercase with our function which returns the first letter of a string. So next time you use it, it behaves something like this-

var text= "JavaScript";
console.log(text.toUpperCase()); //J

 

We have the ‘toUpperCase’ method manipulated!

Note: Don’t get confused between Object & Object.prototype, String & String.prototype etc. Object & String etc. are the native functions while Object.prototype & String.prototype are the actual objects which contain properties and methods from which all objects and primitives of its type can inherit.

 

Adding Your Own Native-like Properties/Methods

We have a length property in ‘String.prototype‘ which can be inherited by all string objects and primitives but there is no any handy way as such to calculate the length of a number. Let’s append a method to ‘Number.prototype‘ so that all the number objects and primitives can use it.

Number.prototype.length= function() {
var numString= this+ ""; //convert number to string
return numString.length; //return string's length
}

 

Now getting a number’s length is as handy as-

var highScore= 1940,
console.log(highScore.length()) //4

 

Native Properties of DOM Elements

Let’s select a paragraph and check it’s prototype chain-

var p= document.querySelector("p");

 

console 3 - Where do javascript native properties come from

 

Prototype chain of our selected paragraph element is clear from the above image.

HTMLParagraphElement.prototype >> HTMLElement.prototype >> Element.prototype >> Node.prototype >> EventTarget.prototype >> Object.prototype >> null.

 

Notice that as for every object in javascript, our ‘paragraph element’ object’s prototype-chain too goes up to Object.prototype and finally ends at null.

 

Checking where a property exists

Using some function like below, we can get the object where the property originally exists-

function checkOrigin(obj, prop) {
  var ob= obj,
  stop= false;
  do {
    if(ob.hasOwnProperty(prop)) {
      return ob;
      stop= true;
    } else {
       ob= ob["__proto__"];
    }
  } while(stop=== false);
}

 

Now let us check where does “style” property used to set inline styles exist-

//HTMLElement.prototype
checkOrigin(p, "style");

 

Let us check for an SVG Element too-

var path= document.querySelector("path");
checkOrigin(path, "style");

 

Now, it should be obvious that all the HTML elements inherit “style” property from ‘HTMLElement.prototype’ and all the SVG Elements inherit the same from ‘SVGElement.prototype’ Similarly, you could check the origin of other properties for any object.

 

Dangers of Manipulating Native Properties and Appending Your Own

Say you were fiddling with toUpperCase method of ‘Object.prototype’ and you did mistakenly overwrite the native function with one of your own

Object.prototype.toUpperCase= function() {
  return this[0];
}

 

Now when you use this method with some string, it will fire unexpected result-

var name= "web";
//w (always gives out the first letter of the string, contrary to your expectation)
name.toUpperCase();

 

Likewise, you could append some method to a prototype with a name and if the browser introduces a similar method or a method with different functionality in future with the same name, your appended method will always overwrite that native one which might be better at performance and has better algorithm than yours one (not the only reasons to prefer the native one over yours). So while naming a method, you are going to append to a prototype object, make sure that your name is so unique that there are no chances of collision with the native one.

 

NOTE

Everywhere in the post, We’ve made use of __proto__ property to deal with the prototype object of an object for the sake of convenience. In fact, this property is obsolete and should be avoided. There are standard ways to get, set and check prototype of an object.

Use this to get prototype object of an object: Object.getPrototypeOf(object);

Use this to set prototype object of an object: Object.setPrototypeOf(object, prototype-object);

Use this to check prototype object of an object: objectFirst.isPrototypeOf(objectSecond);

 

Further Reading

Inheritance and the Prototype Chain (MDN)
Javascript Inheritance

 

Conclusion

Not every property/method you access through an object is contained by that object. Many properties/methods which are supposed to be accessed by multiple similar objects are stored in a prototype object. Every object, whether user-created or a native one, is linked with a prototype chain of objects which it can inherit properties and methods from.

 

Despite the fact that every built-in object has a default prototype object, you could set its prototype to be any object which should be avoided as it might break some critical functionality (imagine setting prototype of paragraph element object to ‘Object.prototype’ directly. You would lose all the properties of objects- ‘HTMLParagraphElement.prototype’, ‘HTMLElement.prototype’, ‘Element.prototype’, ‘Node.prototype’, ‘EventTarget.prototype’, in fact, it won’t remain a paragraph anymore, not even an HTML Element but just a plain object of no use).

 

However you can safely append your methods/properties to standard prototype objects which can be inherited by the child objects just as are done the methods like “toString”. These appended properties/methods should be uniquely named so as to prevent collisions with the ones that browser may introduce in future.

Share on Facebook Tweet on Twitter Post on Google+ Buffer