Stack Exchange
Potential problems with object literal and object constructor in one array?
I want to deeply understand object creation in JavaScript. Generally, I understand the differences between creation methods, etc. Can you describe the difference and influence on working with the object array in these two cases, when I have objects in the array created using two ways below?


function Animal(name, species) {
  this.name = name,
  this.species = species
}

var animals = [
  {name: 'azor', species: 'dog'},
  {name: 'mruczek', species: 'cat'},
  {name: 'burek', species: 'dog'},
];

//Case 1
newAnimal = {name: 'motek', species: 'buterfly'}
animals.push(newAnimal);
console.log(animals);

console.log('---');

//Case 2
newAnimal = new Animal('bongo', 'elephant');
animals.push(newAnimal);
console.log(animals);



I ask because if I use the console it will show
[ { name: 'azor', species: 'dog' },
  { name: 'mruczek', species: 'cat' },
  { name: 'burek', species: 'dog' },
  { name: 'motek', species: 'buterfly' } ]
---
[ { name: 'azor', species: 'dog' },
  { name: 'mruczek', species: 'cat' },
  { name: 'burek', species: 'dog' },
  { name: 'motek', species: 'buterfly' },
  Animal { name: 'bongo', species: 'elephant' } ]

Question
Is it a problem to have objects created using a literal and constructor in same array like in //Case 2?

An array can hold objects and primitives of any type. The display of the console is not standardized. Are you actually experiencing any problems currently?

Nothing wrong with it fundamentally, but if Animal has any methods on the prototype, none of the object literals will have those methods.

So If I want to work with with map(), filter() etc. there will not be difference/problems? Currently I have no problems with It. No I have not methods, just the values.

If you want all the objects to truly be an instanceof Animal, you can use Object.setPrototypeOf() to redefine the objects' prototype:


class Animal {
  constructor (name, species) {
    this.name = name;
    this.species = species;
  }

  greet () {
    return `My name is ${this.name} and I am a ${this.species}`;
  }
}

var animals = [
  {name: 'azor', species: 'dog'},
  {name: 'mruczek', species: 'cat'},
  {name: 'burek', species: 'dog'},
];

animals.push({name: 'motek', species: 'buterfly'});
animals.push(new Animal('bongo', 'elephant'));

animals.forEach(animal => {
  Object.setPrototypeOf(animal, Animal.prototype)
});

console.log(`Are all the animals actually an Animal? ${
  animals.every(animal => animal instanceof Animal)
}`);
console.log(animals.map(animal => animal.greet()));



Or you can use a form of polymorphism to treat all the objects like an Animal by using Function.prototype.call():


class Animal {
  constructor (name, species) {
    this.name = name;
    this.species = species;
  }

  greet () {
    return `My name is ${this.name} and I am a ${this.species}`;
  }
}

var animals = [
  {name: 'azor', species: 'dog'},
  {name: 'mruczek', species: 'cat'},
  {name: 'burek', species: 'dog'},
];

animals.push({name: 'motek', species: 'buterfly'});
animals.push(new Animal('bongo', 'elephant'));

// animals.forEach(animal => {
//   Object.setPrototypeOf(animal, Animal.prototype)
// });

console.log(`Are all the animals actually an Animal? ${
  animals.every(animal => animal instanceof Animal)
}`);
console.log(animals.map(animal => Animal.prototype.greet.call(animal)));



Note that in this case they are still as they were originally defined but you can call prototype methods of Animal and pass each instance as the calling context.
Oh, and the reason the console.log() output is different is because the [Symbol.toStringTag] property, which you can overload:
var newAnimal = {name: 'motek', species: 'buterfly', [Symbol.toStringTag]: 'Animal'}
console.log(newAnimal);
// Animal {name: "motek", species: "buterfly", Symbol(Symbol.toStringTag): "Animal"}


Ok, but what If I want to use a object constructor to add a object to array (shorter syntax) but In console the object should looks like a literal object (for consistency). Is it good/possible at all?

@NetPax Just use a function that returns an object (literal). No need for a constructor.
