Search code examples
javascriptobjectconstructorprototype

Can you add a new dynamic parameter to an object constructor without changing the object constructor?


I'm new to Javascript and learning about objects. I've learned that you can add a new property or method to an object with prototype.

function Person(first, last, age, eyecolor) {
  this.firstName = first;
  this.lastName = last;
  this.age = age;
  this.eyeColor = eyecolor;
}

Person.prototype.nationality = "English";

Now i'm wondering if it's also possible to add a new property with a new parameter without directly assigning the new property or changing the object constructor. So, it becomes:

function Person(first, last, age, eyecolor, nationality) {
  this.firstName = first;
  this.lastName = last;
  this.age = age;
  this.eyeColor = eyecolor;
  this.nationality = nationality;
}

Solution

  • You can do this by wrapping the original constructor in a new function, like this:

    const originalPerson = Person;
    Person = function(first, last, age, eyecolor, nationality) {
        const instance = new originalPerson(first, last, age, eyecolor);
        instance.nationality = nationality;
        return instance;
    };
    

    Live Example:

    function Person(first, last, age, eyecolor) {
        this.firstName = first;
        this.lastName = last;
        this.age = age;
        this.eyeColor = eyecolor;
    }
    
    const originalPerson = Person;
    Person = function(first, last, age, eyecolor, nationality) {
        const instance = new originalPerson(first, last, age, eyecolor);
        instance.nationality = nationality;
        return instance;
    };
    
    const joe = new Person("Joe", "Bloggs", 42, "brown", "English");
    console.log(joe.nationality);

    You can also do it via inheritance:

    const originalPerson = Person;
    Person = class extends originalPerson {
        constructor(first, last, age, eyecolor, nationality) {
            super(first, last, age, eyecolor);
            this.nationality = nationality;
        }
    };
    

    Live Example:

    function Person(first, last, age, eyecolor) {
        this.firstName = first;
        this.lastName = last;
        this.age = age;
        this.eyeColor = eyecolor;
    }
    
    const originalPerson = Person;
    Person = class extends originalPerson {
        constructor(first, last, age, eyecolor, nationality) {
            super(first, last, age, eyecolor);
            this.nationality = nationality;
        }
    };
    const joe = new Person("Joe", "Bloggs", 42, "brown", "English");
    console.log(joe.nationality);

    In both of those cases I've reassigned Person, but you don't have to do that, you could just use ExtendedPerson or some such:

    class ExtendedPerson extends Person {
        constructor(first, last, age, eyecolor, nationality) {
            super(first, last, age, eyecolor);
            this.nationality = nationality;
        }
    }
    

    ...and then use new ExtendedPerson(/*...*/).

    Live Example:

    function Person(first, last, age, eyecolor) {
        this.firstName = first;
        this.lastName = last;
        this.age = age;
        this.eyeColor = eyecolor;
    }
    
    class ExtendedPerson extends Person {
        constructor(first, last, age, eyecolor, nationality) {
            super(first, last, age, eyecolor);
            this.nationality = nationality;
        }
    }
    const joe = new ExtendedPerson("Joe", "Bloggs", 42, "brown", "English");
    console.log(joe.nationality);