Seph Reed
Seph Reed

Reputation: 10938

How to set the constructor of an Object without changing to a new Object?

In this related question, the answer for setting a constructor is like so:

function OldClass() {
    alert("old class with incomplete constructor")
}

function ChangedClass(){
    alert('new class with same prototype and more complete constructor');
}

ChangedClass.prototype = OldClass.prototype;

var theClassIWant = new ChangedClass();

This is not really setting the constructor, it's making a new object and inheriting the prototype. How can I set the constructor of an Object without changing to a new Object? Is it possible?

P.S. I want something like this:

//non working code
var Foo = function() {}

Foo.prototype.constructor = function(bar_val) {
    this.bar = bar_val;
}

var fez = new Foo("cat")
console.log(fez.bar); // outputs: cat;

Upvotes: 1

Views: 81

Answers (2)

Tom
Tom

Reputation: 337

myClass = {
  constructor: function(text){
  console.log(text);
 }
}
let ob = Object.create(myClass);
ob.constructor("old constructor "); //Output: old constructor
myClass.constructor = function(){
 console.log("new constructor ")
}
ob.constructor(); //Output: new constructor

You can do this with every property or function of a class.

Watch this Video here. It explains it perfectly.

Upvotes: 2

Leo
Leo

Reputation: 13838

constructor is a property of the constructor function's prototype, which points to the function itself by default.

When you modify Foo.prototype.constructor, this property points to another function. However, the constructor function Foo remains. So when you create an object, you are still instantiate the constructor function Foo, not the one Foo.prototype.constructor points to.

This is why your code doesn't work. Then let's talk why we need to change the constructor and how to.

In ES5 and before, we take advantage of prototype to simulate a class inheritance mechanism. Which looks like this:

// parent class
function Person(name) {
  this.name = name
}
// define parent method
Person.prototype.say = function() {
  console.log(this.name)
}

// child class
function Coder(name, major) {
  Person.call(this, name) // inherits parent properties
  this.job = 'Coding'
  this.major = major
}
// inherits properties and methods from parent prototype
Coder.prototype = new Person()
// define child method
Coder.prototype.work = function() {
  console.log('I write ' + this.major)
}

// instantiate a child object
var me = new Coder('Leo', 'JavaScript')

console.log(me) // {name: "Leo", job: "Coding", major: "JavaScript"}

Everything looks perfect, but there a problem:

console.log(me.constructor) // Person

What? Isn't me constructed with Coder? Why?

Go back to the first line of this answer, read it again: constructor is a property of the constructor function's prototype.

Originally Coder.prototype.constructor is Coder itself. But with this line: Coder.prototype = new Person(), it got changed. Coder.prototype.constructor now equals Person.prototype.constructor, which is Person.

Well, some would say, try instanceof. Yes, that works:

me instanceof Coder // true

But it's also true for Person, because Coder is a sub class of it:

me instanceof Person // true

This doesn't make sense so we need to fix the constructor problem. That's why we use Coder.prototype.constructor = Coder after Coder.prototype = new Person(), to get back the original constructor.

Full code looks like this:

// parent class
function Person(name) {
  this.name = name
}
Person.prototype.say = function() {
  console.log(this.name)
}

// child class
function Coder(name, major) {
  Person.call(this, name) // inherits parent class
  this.job = 'Coding'
  this.major = major
}
Coder.prototype = new Person() // inherits parent's prototype
Coder.prototype.constructor = Coder // get back constructor
Coder.prototype.work = function() {
  console.log('I write ' + this.major)
}

Upvotes: 2

Related Questions