Denis Beurive
Denis Beurive

Reputation: 435

Object construction: is the prototype really necessary?

I am exploring the concept of heritage in JavaScript and I think that I am missing something.

My goal : I want to create an object that inherits from another object.JavaScript and I think that I am missing something.

As an example, I create an object "Student" that inherits from an object "Personne".

I can reach this goal following two ways:

From my point of view, both ways are good. I mean: apparently, either way works fine.

However, if I look at the second way, then I notice that the object has no prototype. Hence, I think: is it normal? In fact, I prefer the second way because I find it much more elegant.

Note: I give a ready to use script that should be used with NodeJs. I also give the execution results.

So my questions are:

Thanks

Example 1: I declare the properties and the methods within the constructor's prototype

// ---------------------------------------------
// We define a Personne.
// ---------------------------------------------

var Personne = function(inName) { // This is the constructor.
    // Do some initialization.
    console.log("Executing the constructor Personne.");
    if ('undefined' != typeof inName) {
        this.name = inName;
    }
}

var PersonnePrototype = { // This is the prototype.
    name: undefined,
    setName: function(inName) { this.name = inName; },
    getName: function() { return this.name; }
};

Personne.prototype = PersonnePrototype;

// ---------------------------------------------
// We define a Student.
// ---------------------------------------------

var Student = function(inAge, inName) { // This is the constructor.
    // Do some initialization.
    console.log("Executing the constructor Student with inAge=%d and inName=%s.", inAge, inName);
    if ('undefined' !== typeof inAge) {
        this.setAge(inAge);
    }
    if ('undefined' !== typeof inName) {
        this.setName(inName);
    }
}

Student.prototype = new Personne();
Student.prototype.age = undefined;
Student.prototype.setAge = function(inAge) { this.age = inAge; };
Student.prototype.getAge = function() { return this.age; };

Example 2: I declare the properties and the methods within the constructor itself

// ---------------------------------------------
// We define a Personne.
// ---------------------------------------------

var Personne = function(inName) {
    // We define the prototype here.
    this.name = undefined;
    this.setName = function(inName) { this.name = inName; },
    this.getName = function() { return this.name; }

    // Do some initialization.
    console.log("Executing the constructor Personne with inName=%s.", inName);
    if ('undefined' !== typeof inName) {
        this.name = inName;
    }
}

// ---------------------------------------------
// We define a Student.
// ---------------------------------------------

var Student = function(inAge, inName) {
    // We define the prototype here.
    Personne.call(this, inName);
    this.age = undefined;
    this.setAge = function(inAge) { this.age = inAge; };
    this.getAge = function() { return this.age; } 

    // Do some initialization.
    console.log("Executing the constructor Student with inAge=%d and inName=%s.", inAge, inName);
    if ('undefined' !== typeof inAge) {
        this.setAge(inAge);
    }           
}

Ready to use script

if (process.argv.length < 3) {
    console.log('Usage: node "%s" <test number (1|2)>', process.argv[1]);
    return;
}

var test = process.argv[2];

if (test == 1) {

    // -------------------------------------------------
    // Executing test 1.
    // -------------------------------------------------
    console.log("Executing test 1");

    (function() {

        // ---------------------------------------------
        // We define a Personne.
        // ---------------------------------------------

        var Personne = function(inName) { // This is the constructor.
            // Do some initialization.
            console.log("Executing the constructor Personne.");
            if ('undefined' != typeof inName) {
                this.name = inName;
            }
        }

        var PersonnePrototype = { // This is the prototype.
            name: undefined,
            setName: function(inName) { this.name = inName; },
            getName: function() { return this.name; }
        };

        Personne.prototype = PersonnePrototype;

        // ---------------------------------------------
        // We define a Student.
        // ---------------------------------------------

        var Student = function(inAge, inName) { // This is the constructor.
            // Do some initialization.
            console.log("Executing the constructor Student with inAge=%d and inName=%s.", inAge, inName);
            if ('undefined' !== typeof inAge) {
                this.setAge(inAge);
            }
            if ('undefined' !== typeof inName) {
                this.setName(inName);
            }
        }

        Student.prototype = new Personne();
        Student.prototype.age = undefined;
        Student.prototype.setAge = function(inAge) { this.age = inAge; };
        Student.prototype.getAge = function() { return this.age; };

        var Tom = new Student(12, "Tom");
        console.log("The student %s is %d years old.", Tom.getName(), Tom.getAge());
        var Joe = new Student();
        Joe.setName("Joe");
        Joe.setAge(20);
        console.log("The student %s is %d years old.", Joe.getName(), Joe.getAge());
        console.log(Joe.__proto__);
        console.log(Object.getPrototypeOf(Joe));

    })();

    return;
}

if (test == 2) {

    // -------------------------------------------------
    // Executing test 2.
    // -------------------------------------------------
    console.log("Executing test 2");

    (function() {

        // ---------------------------------------------
        // We define a Personne.
        // ---------------------------------------------

        var Personne = function(inName) {
            // We define the prototype here.
            this.name = undefined;
            this.setName = function(inName) { this.name = inName; },
            this.getName = function() { return this.name; }

            // Do some initialization.
            console.log("Executing the constructor Personne with inName=%s.", inName);
            if ('undefined' !== typeof inName) {
                this.name = inName;
            }
        }

        // ---------------------------------------------
        // We define a Student.
        // ---------------------------------------------

        var Student = function(inAge, inName) {
            // We define the prototype here.
            Personne.call(this, inName);
            this.age = undefined;
            this.setAge = function(inAge) { this.age = inAge; };
            this.getAge = function() { return this.age; } 

            // Do some initialization.
            console.log("Executing the constructor Student with inAge=%d and inName=%s.", inAge, inName);
            if ('undefined' !== typeof inAge) {
                this.setAge(inAge);
            }           
        }

        var Tom = new Student(12, "Tom");
        console.log("The student %s is %d years old.", Tom.getName(), Tom.getAge());
        var Joe = new Student();
        Joe.setName("Joe");
        Joe.setAge(20);
        console.log("The student %s is %d years old.", Joe.getName(), Joe.getAge());
        console.log(Joe.__proto__);
        console.log(Object.getPrototypeOf(Joe));

    })();

    return;
}

console.log("Bad test number %d.", test);

Execution:

$ node oo.js 1
Executing test 1
Executing the constructor Personne.
Executing the constructor Student with inAge=12 and inName=Tom.
The student Tom is 12 years old.
Executing the constructor Student with inAge=NaN and inName=undefined.
The student Joe is 20 years old.
{ age: undefined, setAge: [Function], getAge: [Function] }
{ age: undefined, setAge: [Function], getAge: [Function] }

And

$ node oo.js 2
Executing test 2
Executing the constructor Personne with inName=Tom.
Executing the constructor Student with inAge=12 and inName=Tom.
The student Tom is 12 years old.
Executing the constructor Personne with inName=undefined.
Executing the constructor Student with inAge=NaN and inName=undefined.
The student Joe is 20 years old.
{}
{}

Upvotes: 1

Views: 103

Answers (1)

Hoijof
Hoijof

Reputation: 1413

  1. In your example they indeed are equivalent.

  2. Be aware that defining the properties in the constructor will make a copy of them for each instance of the object, but defining them in the prototype will only make one copy (the one in the prototype).

Upvotes: 3

Related Questions