4

I am trying to understand the real difference between keywords new and Object.create()

Explaination:

  • a1 is function while a2 is an object
  • a1 & a2 are having key1 as default property. key2 is being assigned after an instance bxx is created from them. to check whether bxx is independent object itself or just a reference.

"use strict";

function a1() {
  this.key1 = "value 1";
}

let a2 = {
  key1: "value 1"
};

let b1new, b1obj, b2new, b2obj;

try {
  b1obj = Object.create(a1);
} catch (e) {
  console.error("Error a1: ", e.message)
}
try {
  b1new = new a1();
} catch (e) {
  console.error("Error a1: ", e.message)
}


try {
  b2obj = Object.create(a2);
} catch (e) {
  console.error("Error a2: ", e.message)
}
try {
  b2new = new a2();
} catch (e) {
  console.error("Error a2: ", e.message)
}

//let b = new a();

a1.key2 = "value 2";
a2.key2 = "value 2";

if (b1obj) {
  console.log("b1obj.key1: ", b1obj.key1);
  console.log("b1obj.key2: ", b1obj.key2);
}
if (b1new) {
  console.log("b1new.key1: ", b1new.key1);
  console.log("b1new.key2: ", b1new.key2);
}
if (b2obj) {
  console.log("b2obj.key1: ", b2obj.key1);
  console.log("b2obj.key2: ", b2obj.key2);
}
if (b2new) {
  console.log("b2new.key1: ", b2new.key1);
  console.log("b2new.key2: ", b2new.key2);
}

Output:

"Error a2: " "a2 is not a constructor"    
"b1obj.key1: " undefined    
"b1obj.key2: " "value 2"    
"b1new.key1: " "value 1"    
"b1new.key2: " undefined    
"b2obj.key1: " "value 1"    
"b2obj.key2: " "value 2"

Questions:

  1. Why can't use new on a2 ?
  2. Why b1obj.key1 is undefined ?
  3. Why b2obj.key2 is still referring to parent's property?
Rob
  • 14,746
  • 28
  • 47
  • 65
Amit Shah
  • 7,771
  • 5
  • 39
  • 55
  • you can use ``new`` on classes, like ``function ClassName(){}``, when ``a2`` it's just a variable – reconnect Dec 15 '17 at 11:18
  • The object used in Object.create actually forms the prototype of the new object, where as in the new Function() form the declared properties/functions do not form the prototype. – reconnect Dec 15 '17 at 11:21
  • It might have been easier to ask 1 question at a time, or at least split your Snippets into separate ones with just the problems your asking. Anyway, `new` and `Object.create` are not the same. There is a massive difference. – Keith Dec 15 '17 at 11:22
  • @Keith wow what a great suggestion and explanation. so according to your suggestion i should create 3 questions with pasting a same block of code and guess what; i should get an answer that 'There is a massive difference, but don't know what'? – Amit Shah Dec 18 '17 at 05:27
  • @AmitShah Yes, because currently your question requires me scrolling up & down, constantly to find out what your talking about. Would have been really nice if each question & snippet, and results were together. It just makes it easier for people to help. eg. First question, I had to find out were you defined a2, and then when you called new, and of course the question itself, IOW: 3 places up & down, for 1 question. And to top this off, there was another 2 questions. Hope that makes sense, not having a go, but for me your question was hard to answer just because of it's layout. – Keith Dec 18 '17 at 10:55

2 Answers2

2

Please see following answers.

  1. Why can't use new on a2 ?

Because new keyword can only be used with constructors/classes. In Javascript functions can be used as constructors. And a2 is an Object

  1. Why b1obj.key1 is undefined ?

Since you haven't used new keyword for a1, instance will not be created and you won't be able to use properties defined in this. And Object.create() will create an empty object with its prototype set to a1 as object not function (function can also be treated as objects in JavaScript)

  1. Why b2obj.key2 is still referring to parent's property?

Because you haven't overridden it.

What is the real difference between new vs Object.create()

new is used for constructor functions and Object.create() is used to inherit Objects. Also, Object.create() can be used with functions, but then function will act like normal object and not constructor.

Vipin Kumar
  • 6,441
  • 1
  • 19
  • 25
  • 1. so can't i use `a2.prototype = {constructor: function(){}}` something like this then can i use new on a2? I think No, so the question is what is the form of constructor when it's not visible. where is it actually? So overall; The `new` will return a copy of object executing the constructor. while 'Object.create` will just give a new pointer of the object referring to same object. then what happens if i add new lines `a1.prototype.key1 = "value 1 new"; a1.prototype.key2 = "value 2 new";` just above `a1.key2 = "value 2"; a2.key2 = "value 2";` – Amit Shah Dec 18 '17 at 06:43
2
  1. new can be used only with a function or a class. When a function is executed as new User(...), it does the following steps:

    • A new empty object is created and assigned to this.

    • The function body executes. Usually it modifies this, adds new properties to it.

    • If there is no explicit return statement, the value of this is returned.


  1. b1obj.key1 is undefined because Object.create first parameter is an object wich becomes a prototype of created object. In this case it is the a1 function, which doesn't have a key1 property assigned, it only assignes key1 to its this when called.

  1. b2obj has the a2 object as its prototype, so it has access to its key2 property

Suming up: while new keyword is more often used to create new instances of objects from an existing 'template', Object.create is more flexible and allows you to work with a prototype, create property descriptors. For example, you can create a shallow copy of object:

let clone = Object.create(Object.getPrototypeOf(obj), 
                          Object.getOwnPropertyDescriptors(obj));

I suggest you to read this article about new keyword and this one about Object.create and other prototype methods.

UPDATE (about the relationship between object and its prototype): Once you have created a new object, changing its properties does not affect the prototype. For example,

let a2 = {
    key2: "some text"
};
let b2 = Object.create(a2);
a2.key2 = "I am a2";
b2.key2 = "I am b2";

alert(a2.key2 + ", " + b2.key2);

will alert I am a2, I am b2. That's because b2 has its own key2 property. But If it doesn't, JavaScript will look for it in its prototype. You can find a detailed description of the prototype inheritance here

Kirill Simonov
  • 8,257
  • 3
  • 18
  • 42
  • 1
    `Object.create()` is also useful in polyfilling things like ES6 classes: `class A extends B {}` -> `function A() {}; A.prototype = Object.create(B.prototype, Object.getOwnPropertyDescriptors(A));` – Patrick Roberts Dec 16 '17 at 08:25
  • Thanks, I found this answer a bit nearer to my query after going through the provided links. Basically I understood the difference. Now in further process to find another related answer for the post instance/object creation; what happens with the original/child object if we change their properties vise verse.. but for that i will create new post. May be before that if you can provide some helpful links? – Amit Shah Dec 18 '17 at 08:39
  • @Amit I've added some information about inheritance. If the answer was useful, please accept it – Kirill Simonov Dec 18 '17 at 09:11