0

Is there any difference the following code as to prototype assignments. If so, can I learn?

function Person(name, lastname)
{}
Person.prototype.school = `GTU`

function Student(name, lastname) {
    this.name = name
    this.lastname = lastname
}

Student.prototype = Person.prototype                            //   <-----
Student.prototype = Object.create(Person.prototype)             //   <-----
Student.prototype = new Person()                                //   <-----
//Student.prototype.constructor = Student

const me = new Student(`a`, `b`)
console.log(me);

1 Answers1

1

Yes, there are significant differences.

This replaces the Student.prototype property's value with the value of Person.prototype:

Student.prototype = Person.prototype                            //   <-----

This replaces the Student.prototype property's value with a new object that uses Person.prototype as its prototype:

Student.prototype = Object.create(Person.prototype)             //   <-----

(If doing inheritance chains via constructor functions in ES5 and below, that's usually what you want.)

This creates a new object using Person.prototype as its prototype, but also calls the Person constructor to initialize it:

Student.prototype = new Person()                                //   <-----

That's not usually want you want, because you're not creating a Person instance, you're setting up a chain of constructor functions.


As a side note, after you do what you usually want to do:

Student.prototype = Object.create(Person.prototype)             //   <-----

you also want to do this:

Object.defineProperty(Student.prototype, "constructor", {
    value: Student,
    writable: true,
    configurable: true
});

since otherwise, the constructor property will be inherited with its standard value (Person), which isn't appropriate for the prototype object that will be assigned to Student objects. More details about that in my answer here, but fundamentally, to set up the chain in ES5 you'd do this:

function Person(name, lastname) {
    // Since you're accepting these as parameters, you probably want to store them
    this.name = name;
    this.lastname = lastname;
}
Person.prototype.school = `GTU`;

function Student(name, lastname, studentNumber) {
    // Since `Student` derives from `Person`, let `Person` do its initialization
    Person.call(this, name, lastname);
    // Here we do `Student`-specific initialization
    this.studentNumber = studentNumber;
}

// Set up `Student` as a subclass of `Person`
Student.prototype = Object.create(Person.prototype);
Object.defineProperty(Student.prototype, "constructor", {
    value: Student,
    writable: true,
    configurable: true
});

// Example of using `Student`:
const me = new Student(`a`, `b`, 1234);
console.log(me);

I've added a Student-level property (studentNumber) to that to emphasize where each set of properties should be initialized.

In ES2015+, if you're going to use constructor functions to set up inheritance chains, there's basically no reason not to use class syntax. (But only if you're using constructor functions to set up inheritance chains; JavaScript has other paradigms you can use, you don't have to use constructor functions.) That would look like this:

class Person {
    constructor(name, lastname) {
        // Since you're accepting these as parameters, you probably want to store them
        this.name = name;
        this.lastname = lastname;
    }
    // Before too long, you'll be able to replace the assignment that's after the
    // `class` with the following:
    // static school = `GTU`;
}
Person.prototype.school = `GTU`;

class Student extends Person {
    constructor(name, lastname, studentNumber) {
        // Let `Person` do its initialization
        super(name, lastname);
        // Here we do `Student`-specific initialization
        this.studentNumber = studentNumber;
    }
}

// Example of using `Student`:
const me = new Student(`a`, `b`, 1234);
console.log(me);
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875