classMyClass { // basically is a function prop = value; // property, is not written to `MyClass.prototype` constructor(...) { ... } // constructor method(...) {} // method getsomething(...) {} // getter method setsomething(...) {} // setter method
[Symbol.iterator]() {} // method with computed name (symbol here) ['say' + 'Hi']() {} // `[...]` computed `sayHi()` }
class field
dynamic this
If an object method is passed around and called in another context, e.g. setTimeout(), this won’t be a reference to its object any more.
we can pass a wrapper-function, such as setTimeout(() => button.click(), 1000)
Bind the method to object. click = () => {this...} class field is created with this inside it referencing that object. We can pass click function around anywhere.
Class inheritance
extends keyword
class Rabbit extends Animal: it sets Rabbit.prototype.[[prototype]] to Animal.prototype
super keyword
overriding a method
super.method() to call a parent method.
super() to call a parent constructor (inside our constructor only)
1 2 3 4 5 6 7
classRabbitextendsAnimal { hide() {...} stop() { super.stop(); // call parent stop this.hide(); // and then hide } }
overriding constructor
Constructor in inheriting classes must call super(...), and do it before using this.
internals, [[HomeObject]]
When a function is specified as a class or object method, its [[HomeObject]] property becomes that object.
it is defined for methods(not function properties) both in classes and in plain objects.
for objects, methods must be specified exactly as method(), not as method: function().
overriding class fields
When the parent constructor is called in the derived class, parent constructor always uses its own field value, not the overridden one.
But it uses the overridden method instead.
Static properties and methods
Static properties are used when we’d like to store class level data, like User.property = ... Usually create and clone methods.
Protected properties are usually prefixed with an underscore _, that’s a well-known convention, not enforced at the language level.
Getter/setter functions
Getter/setter functions are preferred, because flexibility and multiple arguments. E.g. getNumber(), setNumber(num)
Private, ##property
##: language level.
Protected fields are naturally inheritable. Unlike private ones.
We can’t access private field from outside or from inheriting classes.
Extending built-in classes
No static inheritance in built-ins
Normally, when one class extends another, both static and non-static methods are inherited.
E.g. Date extends Object, so their instances have methods from Object.prototype.
But Date.[[Prototype]] doesn’t reference Object, so there is no Date.keys() static method. In other words, there is no link between Date and Object, so built-in classes don’t inherit statics from each other.
That’s an important difference of inheritance between built-in objects compared to what we get with extends.
Class checking: instanceof
instanceof operator
syntax
obj instanceof Class: returns true/false
constructor functions:new Class() instanceof Class
let sayMixin = { say(phrase) { alert(phrase); } };
// mixin, can make use of inheritance inside themselves let sayHiMixin = { __proto__: sayMixin, // or we could use Object.create to set the prototype here