Reputation: 899
Does anyone know why in the code example below JS throws an error when ES6 classes are just syntactical sugar on top of the constructor function and prototype pattern?
// Example 1
class Cat {
meow() {
console.log('Meow meow!')
}
}
let kitty = {};
Object.assign(kitty, Cat.prototype);
kitty.meow(); // TypeError: kitty.meow is not a function
Why then this code snippet works when it should be functionally the same as the one from above?
class Cat {
}
Cat.prototype.meow = function() {console.log('Meow meow!')}
let kitty = {};
Object.assign(kitty, Cat.prototype);
kitty.meow(); // Meow meow!
Upvotes: 0
Views: 79
Reputation: 11313
Object.assign
copies the enumerable properties of one or more source objects to a target object. Unless defined so, methods are by default non-enumerable. Object.create
on the other hand, can create a new instance of your class if, for some reason, you want to do it this way.
class Cat {
meow() { console.log('Meow meow!') }
}
let kitty = Object.create(Cat.prototype);
kitty.meow();
An example to illustrate how Object.assign
works would be the following. In the example below, using Object.assign
copies the enumerable properties of the two Cat
instances to kitten3
, which has a mix of their properties but is NOT itself a Cat
instance.
var id = 1;
class Cat {
constructor(name) {
this.id = id++;
if (name) this.name = name;
}
}
let kitty1 = new Cat("Lucy");
console.log(kitty1.id, kitty1.name, kitty1 instanceof Cat);
let kitty2 = new Cat();
console.log(kitty2.id, kitty2.name, kitty2 instanceof Cat);
let kitty3 = {};
Object.assign(kitty3, kitty1, kitty2);
console.log(kitty3.id, kitty3.name, kitty3 instanceof Cat);
In your updated code where you set Cat.prototype.meow = function() {}
, you do so directly which makes it an enumerable property of the object (prototype), which is why Object.assign
works. You can see the difference using Object.keys
. A closer equivalent to the first declaration would be to define the method using Object.defineProperty
and making it non-enumerable:
class Cat1 {
meow() { console.log('Meow meow!') }
}
class Cat2 {}
Cat2.prototype.meow = function() { console.log('Meow meow!') }
class Cat3 {}
Object.defineProperty(Cat3.prototype, "meow", {
value: function() { console.log('Meow meow!') },
enumerable: false
});
console.log("Cat1: ", Object.keys(Cat1.prototype));
console.log("Cat2: ", Object.keys(Cat2.prototype));
console.log("Cat3: ", Object.keys(Cat3.prototype));
Upvotes: 6