Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In JavaScript, what is the ultimate root, Object or Function?

In JavaScript is Object the root of all entities or Function is the root?

For example in the following source objects-functions-and-prototypes-in.html, first the author says "Every entity in Javascript is an object", and later it says "any new object can only be created as an instance of a function (even when you do 'var a = new Object;', Object is a function btw)". The author is basically contradicting himself as far as I can see.

And I see the same chaotic comments in so many other resources on JavaScript. In Java it is easy, you know the first entity in any class Hierarchy is the Object class, but in JavaScript, all I see is chaos.

So, can someone please clarify if Object comes first or Function? What is the root.

like image 227
user1888243 Avatar asked Jan 04 '13 17:01

user1888243


People also ask

What is JavaScript function object?

In JavaScript, functions are first-class objects, because they can have properties and methods just like any other object. What distinguishes them from other objects is that functions can be called. In brief, they are Function objects.

Which object is in the top root of JavaScript?

The window is at a root/top level at the JavaScript object hierarchy. It is a global/root object in JavaScript and it is the root object of the Document object model(DOM);

What is the object type in JavaScript?

Object Methods Object properties can be both primitive values, other objects, and functions. An object method is an object property containing a function definition. JavaScript objects are containers for named values, called properties and methods.

What is object object in JavaScript?

[object, object] is the string representation of a JavaScript object data type. You'll understand better as we go further in this article. There are two main contexts where you'll encounter such an output: When you try display an object using the alert() method (most common).


2 Answers

I believe the end of the line is Object.prototype, which is an object. This is what makes me think so:

Function.prototype;                    // the empty function object
Function.prototype.__proto__;          // the default Object prototype
Object.prototype;                      // the default Object prototype
Object.prototype.__proto__;            // null

The ECMAScript 5.1 specification states it like this:

  1. In 15.3.4 Properties of the Function Prototype Object:

    The value of the [[Prototype]] internal property of the Function prototype object is the standard built-in Object prototype object

  2. And in 15.2.4 Properties of the Object Prototype Object

    The value of the [[Prototype]] internal property of the Object prototype object is null

like image 82
bfavaretto Avatar answered Sep 28 '22 12:09

bfavaretto


Here's what the MDN docs for Object.prototype have to say:

all objects inherit methods and properties from Object.prototype, although they may be overridden (except an Object with a null prototype, i.e. Object.create(null)).

In other words, Object.prototype is the root of almost all objects. Both Object and Function are children of Function.prototype, which is itself a child of Object.prototype.

I find inheritance in Javascript to be far easier to understand when I ignore the constructor functions, and instead focus on prototype chains. Doing this, for me, makes both the questions as well as the answers simpler; questions like:

  • what is the prototype chain of an object?
  • given two objects x and y, is x in y's prototype chain? (or: does y inherit from x?)

You can easily investigate prototype chains yourself with this little snippet (helpful docs here):

function getPrototypes(obj) {
    var protos = [],
        parent = obj;
    while ( true ) {
        parent = Object.getPrototypeOf(parent);
        if ( parent === null ) {
            break;
        }
        protos.push(parent);
    }
    return protos;
}

According to this function, primitives don't have prototypes:

> getPrototypes(3)
TypeError: Object.getPrototypeOf called on non-object

So let's leave primitives out of the picture. For objects, the hierarchy looks like this (where the children are indented to the right of their parent). As far as I know, true multiple inheritance is impossible in Javascript, and so every object has a single parent, with the exception of Object.prototype, which has no parent:

  • Object.create(null)
  • Object.prototype
    • arguments
    • Object.create(Object.prototype)
    • {}
      • Object.create({}) -- assuming {} is the object from the previous line, not a separate new object
    • JSON
    • Math
    • Array.prototype
      • []
      • new Array()
    • Function.prototype
      • Array
      • Object
      • Function
      • Number
      • Boolean
      • String
      • RegExp
      • function MyFunction() {}
      • Object.keys
      • Object.prototype.toString
      • Object.prototype.toString.call
      • getPrototypes
    • MyFunction.prototype
      • new MyFunction()
    • String.prototype
      • new String('abc')
        • Object.create(new String('abc'))
    • Number.prototype
      • new Number(41)
    • Boolean.prototype
      • new Boolean()
      • new Object(false)
    • RegExp.prototype
      • /a/

This is very confusing! Notice that for most cases, X.prototype is not a prototype of X! If we had some better terminology, the situation would probably be improved; however ... we don't :( As you can see, constructors such as Number and Boolean are in a separate sub-hieararchy from the objects they produce. Also, Object itself inherits from Function.prototype inherits from Object.prototype.

If you try these examples out, you will also find that using the constructor property is a poor way to inspect an object's prototypes, for a couple of reasons. Given var str1 = new String('abc'); var str2 = Object.create(str1);, here's why:

  1. an object can be an instance of multiple constructors: str1 instanceof String and str1 instanceof Object are both true. This isn't reflected in the constructor property: str1.contructor === String

  2. sometimes, we can't find a constructor function for each object in an object's prototype chain: Object.getPrototypeOf(str2).constructor === String. This is because the constructor property is inherited from String.prototype: both str1.hasOwnProperty('constructor') and str2.hasOwnProperty('constructor') are false, while Object.getPrototypeOf(str1).hasOwnProperty('constructor') is true. Fortunately, you can use the Object.prototype.isPrototypeOf method for this instead: str1.isPrototypeOf(str2) is true.

like image 21
Matt Fenwick Avatar answered Sep 28 '22 10:09

Matt Fenwick