Search code examples
javascriptobjectinheritanceprototypeprototypal-inheritance

new keyword, new Object() and Object.create() in Javascript


I need some clarification regarding object instantiation and inheritance. Consider the following code and subsequent observations:

function TestObject() {
  this.TestProperty1 = "TestProperty1";
  this.TestFunction1 = function() {
    console.log(this.TestProperty1);
  }
}

TestObject.prototype.TestProperty2 = "TestProperty2";
TestObject.prototype.TestFunction2 = function() {
  console.log(this.TestProperty2);
}

new keyword

let TestInstance1 = new TestObject();
console.log(TestInstance1);

The output is exactly what I would expect given my OOP experience. TestInstance1 is of the type TestObject and it has access to both its members and its prototype members.

new Object()

let TestInstance2 = new Object(TestObject.prototype);
console.log(TestInstance2);

The output indicates that TestInstance2 is of the type Object and not TestObject however it gets a constructor property which references TestObject. It only has access to the prototype members of TestObject.

Object.create()

let TestInstance3 = Object.create(TestObject.prototype);
console.log(TestInstance3);

The output indicates that TestInstance3 is of the type TestObject but it only has access to its prototype members.

Questions

Why would one want to use the new Object() method instead of the new keyword method? It seems weird to return an Object instance with a reference to the type passed to its constructor instead of simply returning an instance of the type itself.

Was the new keyword method available in the first edition of the standard just like the new Object() method was? I have the impression that it was added later since I don't see any reason to use the new Object() method instead of the new keyword method.

Since Object.create() was added rather recently to the language, what issue was it intended to solve?


Solution

  • The following line:

    TestObject.prototype.TestProperty2 = "TestProperty2";
    

    Modifies all TestObject instances, which is usually not what you are trying to achieve.

    The Object.create() method is used to achieve classical inheritance. Such as:

    EnchancedTestObject.prototype = Object.create(TestObject.prototype);
    

    So instead of inheriting from the TestObject directly, you are inheriting from Object with a specified prototype. Any changes made to it, will not affect the initial one.

    EnchancedTestObject.prototype = new TestObject();
    

    You also usually don't want to create a new TestObject instance here. What would happen if TestObject expected arguments? Which one would you pass? What if calling the TestObject constructor has side effects?

    The solution is to hook up TestObject.prototype into the prototype chain.