Question on creating new objects using constructor functions [Solved]

Hi,

So my question is :

When using the “new” keyword ot create objects using constructor functions, does every object created by a constructor function have its own copy of functions defined in the constructor function or does it only have a reference to the function defined in the constructor function?
( I know that for primitives, objects and arrays each newly created object has its own copy, but does it work the same way for functions too?)

Example:

function Car (make, model, age) {
  this.make = make;
  this.model = model;
  this.age = Number(age);
  function printCarDetails() {
    console.log("make = " + make + ", model = "+ model + ", age = " + age);
  }
}

Now, if I want to create a new car, I write the following:

var myCar = new Car("Nissan", "Sentra", "1988");
myCar.printCarDetails();

Output: “make = Nissan, model = Sentra, age = 1988”

Now, suppose you redefine the printCarDetails() function of the “Car” constructor function:

Car.printCarDetails = function() {
  console.log("This function has changed");
}

Now, call car.printCarDetails();

> myCar.printCarDetails();

What will be the output result -

(a) Still the same - “make = Nissan, model = Sentra, age = 1988” OR
(b) “This function has changed”


As an addendum to the question,

When a new object is created by the constructor function, does the constructor function do a “deep” or “shallow” copy of the objects and arrays defined in the constructor function ?

Thanks

You should always define functions in prototype, like this: Car.prototype.printCarDetails = ...

The purpose of the question is to understand the internals of how JavaScript works under the hood.

So, even though I would use the prototype property in the real world, I’m focusing on understanding important fundamentals of the language (for example, what and how exactly are new objects created by the constructor function - are objects and arrays deep copied (or deep cloned) in the newly created object or is it simply a shallow copy (reference copy) ? Also, even though number, string, boolean types are copied by value, does the same thing happen with functions? i.e. is the function object (printCarDetails) deep cloned in the new object or is it just a reference to the function that is copied over ?)

This has no effect on any object created by using new Car(...). Rather. this defines a new property for Car as an object. To answer the question, you’ll get (a).


I created a constructor function that defines an array in it. Objects created with the constructor call has their own copies of the array.

Ok, so I discovered a whole bunch of things wrong with my code above!.

Let me list the things that are wrong so that I may better understand JavaScript.

[1] The way I have defined the function printCarDetails() inside the constructor function Car,

function printCarDetails() {
console.log("make = " + make + ", model = "+ model + ", age = " + age);

does not create a “printCarDetails” property on Car or any new object created by it. It creates a private function (aka method) in Car. Being private, this function is not accessible outside Car. (Private methods are inner functions of the constructor. Also, private methods cannot be called by public methods. Public methods are those that are defined on the prototype of the function) (http://javascript.crockford.com/private.html)

It gives me the following error when I execute “myCar.printCarDetails();”

TypeError: myCar.printCarDetails is not a function

To make “printCarDetails” a property of any object created from Car I need to use -

this.printCarDetails = function() {
console.log("make = " + make + ", model = "+ model + ", age = " + age);
};

Now when I execute “myCar.printCarDetails();”,
it displays “make = Nissan, model = Sentra, age = 1988”

[2] As @kevcomedia correctly pointed out:

Car.printCarDetails = function() {
  console.log("This function has changed");
}

This has no effect on any object created by using new Car(…). Rather. this defines a new property for Car as an object.

[3] The constructor function, when called using new, creates “deep” clones/copies of Objects and Arrays and Functions for the newly created objects.
For example,

If we then define 2 objects as such:

var myCar = new Car(“Nissan”, “Sentra”, “1988”);
var otherCar = new Car(“Toyota”, “Camry”, “1993”);

on running the following tests, we get these results:

(a) console.log(myCar.internalCarObject === otherCar.internalCarObject); (False)
(b) console.log(myCar.printCarDetails === otherCar.printCarDetails); (False)
(c) console.log(myCar.internalArray === otherCar.internalArray); (False)
(d) console.log(myCar.internalCarObject);

{ make: 'Nissan',
  model: 'Sentra',
  age: '1988',
  internalinternalObject: { name: 'value' } }

[4] This is why, as @laney stated, [quote=“laney, post:3, topic:23705”]
Car.prototype.printCarDetails = …
[/quote]

it is better to use the “prototype” property of Car and declare functions in it. This way, objects created from the Constructor Function don’t have their own instances of the Function (which uses up extra memory unnecessarily). All instances of Car can now share the same function.

This is incorrect. All copies in JS are shallow unless you really go out of your way to deep copy, and you’re not doing that here: rather than copying anything, you are explicitly creating entirely new objects and arrays every time you invoke the constructor, and assigning them to properties on this (which JS fabricates for you when you use new).

I found this online snippet which suggests roughly how the “new” operator in JavaScript would be implemented:

(Taken from http://www.2ality.com/2014/01/new-operator.html)

1 Like