3 ms·
To be clear: in practice there are three ways to use inheritance in JS: 1) Prototypes with constructors using the "new" keyword (ES3+): function Foo (name
by pluma 9y ago
To be clear: in practice there are three ways to use inheritance in JS:
1) Prototypes with constructors using the "new" keyword (ES3+):
function Foo (name) {
this.name = name;
}
Foo.prototype.hello = function () {
return `Hello ${this.name}!`;
};
let foo = new Foo("world");
console.log(foo.hello()); // Hello world!
2) Plain prototypes with Object.create (ES5+):
let bar = {
name: 'world',
hello: function () {
return `Hello ${this.name}!`;
}
};
let baz = Object.create(bar);
baz.name = 'Wisconsin';
console.log(bar.hello()); // Hello world!
console.log(baz.hello()); // Hello Wisconsin!
3) Classes (ES2015+):
class Qux {
constructor (name) {
this.name = name;
}
hello () {
return `Hello ${this.name}!`;
}
}
let qux = new Qux("world");
console.log(qux.hello()); // Hello world!
Note how all three examples do (roughly) the same thing but in slightly different ways.
Inheritance in #1 is a bit awkward (which is why before ES2015 there were myriads of different inheritance libraries).
In #2 it's fairly straightforward but type checks are unintuitive because there really aren't any types involved (instanceof requires a constructor).
In #3 both inheritance and type checks are fairly straightforward but it also uses more abstractions, which can make it more difficult to understand conceptually (especially when coming from a language like Java or C# which is syntactically similar).
IMO #1 is the worst of both worlds because the behaviour of the "new" keyword and the special "prototype" property are difficult to understand and the constructor looks like a regular function but expects to be called in a special way (using the "new" keyword) and will break in unexpected ways if called as a normal function:
> TypeError: Cannot set property 'name' of undefined
(or worse: outside strict mode it might not fail and actually try to write to the global scope -- so remember to always "use strict")
While the value of a class is also a constructor function, calling it without "new" will break with a distinct error that makes the mistake obvious and easy to understand:
> TypeError: Class constructor Qux cannot be invoked without 'new'
- azangru 9y agoThanks :-) I've never used Object.create for inheritance (although I heard it was a favorite of Douglas Crockford's at some point). And the syntactic sugar of es2015 classes is so appealing I never wrote constructor functions on a regular basis. What's so conceptually difficult about es2015 classes that confuses people? They always felt intuitive to me. A bit restrictive perhaps, because you don't have private methods, or instance properties, and if you want to call super in a method you have to do it before anything else, but other than that — nothing especially confusing.