0

What is the main difference between these two Person declaration?

Via constructor:

var Person = function (name, age) {
    this.name = name;
    this.age = age;
    this.setName = function (name) {
        this.name = name;
    };
    this.setAge = function (age) {
        this.age = age;
    };
};

var bob = new Person('Bob', 15);

Via object literal:

var defaultPerson = {
    name: '',
    age: '',
    setName: function (name){
        this.name = name;
    },
    setAge: function(age){
        this.age = age;
    }
};

defaultPerson.setName('Fill');
defaultPerson.setAge(15);

Are there some restrictions imposed on these two created objects?

10
  • 3
    With the first solution you can create multiple instances, with the second it's not obvious what the relation between p and defaultPerson is. Commented Aug 22, 2015 at 22:05
  • There's no Person.prototype Commented Aug 22, 2015 at 22:05
  • @zerkms Yes, I updated the question. p is defaultPerson. Commented Aug 22, 2015 at 22:07
  • 2
    @JohnWinter so with first you may create multiple persons, with the second you cannot. That's the most significant difference in this case. Commented Aug 22, 2015 at 22:08
  • Ok, I see. Thank you. Commented Aug 22, 2015 at 22:08

5 Answers 5

3

With the constructor way you can create multiple instances (pretty equivalent to a class):

var person1 = new Person('a',12);
var person2 = new Person('b',13);

While the other way will only create one instance of the class.

var person1 = {
  // blah
};

for person2 you will need to create a new object:

var person2 = {
  // blah
};

In the ctor way you can also:
1. Run code.
2. Pass parameters.
3. Have a prototype and support inheritance\expansion of the object.

Sign up to request clarification or add additional context in comments.

3 Comments

#3 is not really an advantage of constructors. You could do var person1 = Object.create(defaultPerson) as well
@Bergi - How will Object.create get you a prototype?
Every object can be a prototype. It doesn't need to sit on a .prototype property of something to be inherited from.
2

That is a broad question about OO in Javascript and inheritance methods. I cannot cover it really in a post's answer, and you should make some search and reading, but here is some points to consider:

  1. the first is called Function Constructor, usually the first letter is capitalized by convention. Now, let us assume that you want to add some shared methods to the object to be created by 'new' Person: Then you would set the .prototype property of the Person() to an object that holds such shared methods.
  2. In the the second method, you have just made a normal object and used its methods. But I assume what you actually wanted to do, is to use this as a prototype to create other objects. Consider the following code:

    var fill = Object.create(defaultPerson);
    // fill will be created and its internal prototype is set to the defaultPerson object.
    
  3. The second method is usually referred to as Pure Prototypal Inheritance, some including myself, find it more natural to Javascript.

  4. The first method is a mimic to constructors in classical OOP languages. Now in ES6 (2015) is even more reinforced by adding the keywords 'calss, extends';

  5. After all; both are valid methods to create objects and implement inheritance in Javascript. Make a choice and stick to it for convenience.

Good luck, hope this helps a bit.

Comments

0

There are 3 main differences:

When object is created using literal...

  1. .__proto__ property is set to Object.prototype
  2. .constructor is set to function Object(){...}
  3. It wasn't created using a Constructor Function so creating similar object would require duplication.

However, if you run this code...

function a(){}
var obj = new a();

//then

obj.constructor  == a;
obj.__proto__ == a.prototype;

another practical difference I can think of this:

var o = {
     a : 1,
     b : this.a + 2
};

in this case b will be either undefined, give an error or be attributed to whatever this.a refers to now. Everything but it won't be 1. Where as using constructor function method this would work...

function Math() {
    this.a = 1;
    this.b = this.a +2 ;
}
var m = new Math();

Comments

0

If you wish to apply OOP in js then using protype is better than using constructor. As js object will pass it's properties to it's child as prototypes.

Comments

0

The function constructor creates a new object and you have to do three additional things to assimilate conventional class/inheritance design:

  1. Call the base class: base.call(this, props...);
  2. augment the prototype: obj.prototype.func = function(){};
  3. re-assign the constructor

ECMA6 will introduce new syntax, like extend and Class, but JS is a prototypal language. This just means that every time you create an object var o = {}; It's not truly an empty object, it has no properties but sitting underneath in the dark waters of the compiler, a secondary object exists called the prototype, here the compiler links back to another object.

When you ask the compiler to get a value, e.g. console.log(this.x) it looks first at the objects own properties, if it can find it, it adorns a snorkel and dips its head into the tepid waters to search through the objects prototype. If its not there, the compiler must put on its wet-suit to dive deeper into the murky waters. If the compiler is now on the sea bed, it can search no more and its at the lowest level object called Object. The compiler will then cough and splutter back undefined as it gathers its breathe for another loop through the abyss.

So the closer your properties and functions are to the objects immediate context, the better your code will perform. If you try to chain many prototypes, the compiler will get the bends after the amount of diving and resurfacing it needs to do.

When you create a class in JS, you are creating instance properties and setting the prototype:

var Cat = function() {
    this.age = 3;
    this.colour = 'black';
};

Cat.prototype.age = function() { console.log(this.age); };

Using the new keyword creates a blank object and sets the context to this, so in Cat we're just augmenting the properties of the current context, e.g. this.age = 3;

The compiler already knows about the Cat.prototype and these functions are linked to your object and not copied verbatim to your object.

The new way to create objects is clunky and the following embraces prototypal delegation; call it mixins, extensions, inheritance or whatever, the whole point is that we can augment objects with other objects and put the functions on the prototype, so they are seen by all instances.

var manufacturer = {
    id:'manufacturer',
    constructor : function (args) {
        this.boss = args.boss || 'Bernie Ecclestone';
      this.country = args.country || 'UK';    
        return this;
    }
};

var vehicle = {
    id:'vehicle',
    constructor : function (args) {
        this.colour = args.colour || 'blue';
      this.wheels = args.wheels || 2;     
        extend.call(this, manufacturer, args);
        return this;
    }
};

var driver = {
    id:'driver',
    constructor : function (args) {
        this.name = args.name || 'John';
        return this;
    },
    info : function () { console.log(this.name); }
};

var engine = {
    id:'engine',
    constructor : function (args) {
        this.type = args.type || 'V6';
        this.fuel = args.fuel || 'petrol';
        return this;
    },
    tune : function () { 
        this.type = 'super-charged';
        this.fuel = 'ethanol';
        console.log('Car now ' + this.type + ' with ' + this.fuel); 
    }
};

var car = {
    id:'car',
    constructor : function (args) {       
        extend.call(this, vehicle, args);
      extend.call(this, driver, args); 
        extend.call(this, engine, args);   
        return this;
    },
    info : function () { 
        console.log('boss: ' + this.vehicle.manufacturer.boss);
        console.log('country: ' + this.vehicle.manufacturer.country);
        console.log('driver: ' + this.driver.name);
        console.log('colour: ' + this.vehicle.colour);
      console.log('wheels: ' + this.vehicle.wheels);
      console.log('type: '   + this.engine.type);
      console.log('fuel: '   + this.engine.fuel);
        console.log('\n');
  }
};

function extend(proto, args){
  this[proto.id] = Object.create(proto);
  proto.constructor.call(this[proto.id], args);
}

var ferrari = Object.create(car).constructor({
    boss: 'Maurizio Arrivabene',
    country:'Italy',
    name: 'Steve', 
    colour: 'red', 
    wheels: 4, 
    type:'100cc', 
    fuel:'diesel'
});

var lotus = Object.create(car).constructor({
    name: 'Jenson Button'
});

var mclaren = Object.create(car).constructor({
  type:'hybrid',
    fuel:'battery/petrol'
});

ferrari.engine.tune();
ferrari.info();
/*
Car now super-charged with ethanol
boss: Maurizio Arrivabene
country: Italy
driver: Steve
colour: red
wheels: 4
type: super-charged
fuel: ethanol
*/

lotus.info();
/*
boss: Bernie Ecclestone
country: UK
driver: Jenson Button
colour: blue
wheels: 2
type: V6
fuel: petrol
*/

mclaren.info();
/*
boss: Bernie Ecclestone
country: UK
driver: John
colour: blue
wheels: 2
type: hybrid
fuel: battery/petrol
*/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.