I'm that kind of a person who needs to know everything in depth... So, I've been going through many taught subjects and I set my foot into depths of Prototype-inheritance.
I have a clear vision of how it works in ES5 (Every function has this special prototype property, which points to an object on which it is based on. This object has .constructor property, which points back to the function etc.).
So, now let's see ES5 example:
function Bunny(name) {
this.name = name
}
Bunny.prototype.sayName = function() {
console.log('Im',this.name)
}
This one is pretty clear: function Bunny gets argument name
which's going to be assign to a new object.
Next line adds function to the function's prototype, which's going to return current name.
Let's see ES6 class now:
class Fox{
constructor(name){
this.name = name;
}
sayName() {
console.log('Im', this.name)
}
}
Same stuff here: Constructor
here is like our Bunny function. But sayName
in fox is not the same as sayName
in Bunny.
Let's create the instances:
let bunny = new Bunny('Henry');
let fox = new Fox('Jerry');
And now, check their prototypes:
console.log(Object.getPrototypeOf(bunny))
console.log(Object.getPrototypeOf(fox))
What do we get?
//using repl.it - ES6
{ sayName: [Function] }
{}
Why is that?
I thought it might be because we set function sayName
on Bunny's prototype directly. So I've changed it to this:
function Bunny(name) {
this.name = name
//Warning - Bad practice ahead!
this.sayName = function() {
console.log('Im',this.name)
}
}
Result:
//using repl.it - ES6
{}
{}
That would have sense, if not this:
console.log(bunny.hasOwnProperty('sayName'))
console.log(fox.hasOwnProperty('sayName'))
Which means, fox
does not own sayName
on him, either prototype shows it has it. Am I missing something here? Why They are different?
ES6 class allows the developers to instantiate objects using the new operator. ES5 function constructors focus on how the objects are instantiated. They also ensure the developer that this keyword which is basically used inside the class only refers to the object that is being created by the developer.
ES6 provides high performance due to advanced features added to it and code optimization. ES6 has less community support than ES5 as it is a recent update on ES5 and not all browser supports it.
In the ES5 version, there are no classes; a function is used to make an object directly. However, the ES6 version uses the keyword class to define a class. The underlying concept is more or less the same. ES6 just cleans up the syntax.
In ES6 classes all methods are non-enumerable, so you when you log a prototype of an instance of an ES6 class, you get something that looks like an empty object.
See this example:
const obj = new (class {method() {}});
console.log(Object.getPrototypeOf(obj)); // {}
console.log(typeof Object.getPrototypeOf(obj).method); // function
In ES5 you define a method by assigning it to a property of the class prototype, which makes it enumerable. If you wanted to achieve the same effect as with ES6 classes, you could use Object.defineProperty()
instead:
const TestClass = function TestClass() {};
Object.defineProperty(TestClass.prototype, 'method', {
value: function() {},
writable: true,
enumerable: false,
configurable: true,
});
const obj = new TestClass();
console.log(Object.getPrototypeOf(obj)); // {}
console.log(typeof Object.getPrototypeOf(obj).method); // function
And fox.hasOwnProperty('sayName')
returns false
because hasOwnProperty()
checks only for own properties, and sayName
is in the prototype chain. If you want to check for properties in the prototype chain too, you can use the in
operator: 'sayName' in fox
returns true
.
See also Enumerability and ownership of properties on MDN.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With