Day 14, 15, 16 - Intermediate JS: Classes, Mix-ins, Inheritance - extends
19 February, 2024
42
42
0
Contributors
- Have no clue where to start a project?
- Start from inside i.e., layout the foundation & framing before building a wall, Check if the entire game can be played only in console
- With very limited interface, it makes it very easy to interact from outside
- Great read: https://www.ayweb.dev/blog/building-a-house-from-the-inside-out
- Use
dataset
read-only property (ofHTMLElement
interface) which gives read/write access to custom properties - Make a note that
dataset
cannot be written directly, instead it has to be done thru custom properties ondataset
- Make a note that
- Google’s javascript styleguide - https://google.github.io/styleguide/javascriptguide.xml
- Accessor property - link
get
andset
Object.defineProperty
({}, ‘prop’, {});Object.defineProperty({}, 'prop', {
get() {
return 1;
},
});- Example
function User(name, birthday) {
this.name = name;
this.birthday = birthday;
// age is calculated from the current date and birthday
Object.defineProperty(this, "age", {
get() {
let todayYear = new Date().getFullYear();
return todayYear - this.birthday.getFullYear();
}
});
}
let john = new User("John", new Date(1992, 6, 1));
alert( john.birthday ); // birthday is available
alert( john.age ); // ...as well as the age
- Example
- Class basic syntax - https://javascript.info/class#not-just-a-syntactic-sugar
- Class is function in js 🙂 with few important differences from writing it the regular way using a constructor.
- A special internal property called
[[IsClassConstructor]]: true
is added when defined usingclass
keyword - So unlike regular function, this property is checked & it must be called with
new
operator
- So unlike regular function, this property is checked & it must be called with
class
sets the enumerable flag to false for all the methods inprototype
- This enables, when iterating over an object using
for ... in
, we wouldn’t get the class methods.
- This enables, when iterating over an object using
class
also makes sure thatuse strict
is used for all the code within the class construct.
- A special internal property called
- A property/field is declared using
property = value
(Old browsers need polyfill) - A method is declared in the form
method() {}
- notice that it doesn’t use the=
signclass MyClass {
prop = value; // property
constructor(...) { // constructor
// ...
}
method(...) {} // method
get something(...) {} // getter method
set something(...) {} // setter method
[Symbol.iterator]() {} // method with computed name (symbol here)
// ...
}
- extends - Use of Inheritance
- Use
extends
to create a child class from a Parent class - The parent class evaluates to a constructor function.
- The parent class (Any constructor) needs to satisfy these 2 conditions:
- It can be called with
new
keyword - It needs to have prototype property
- It can be called with
- Child class (derived class) must return an object or
undefined
. - If the parent class constructor returns an object, that object will be used as the
this
value for the derived class when further initializing class fields. This trick is called "return overriding", which allows a derived class's fields (including private ones) to be defined on unrelated objects.
- If the parent class constructor returns an object, that object will be used as the
- composition instead of inheritance
- In general, unless there's a very good reason to use inheritance, it's better to use composition instead. Composition means that a class has a reference to an object of another class, and only uses that object as an implementation detail.
- Use
- Mix-ins allow reusability - link
A class can have only one ParentClass and mix-ins can be used to get the functionality of multiple classes which cannot be achieved by using
extends
on a single parent class.A Mix-in is a function with a superclass as input and a subclass extending that superclass as output can be used to implement mix-ins:
const calculatorMixin = (Base) =>
class extends Base {
calc() {}
};
const randomizerMixin = (Base) =>
class extends Base {
randomize() {}
};class Foo {}
class Bar extends calculatorMixin(randomizerMixin(Foo)) {} - Use
#
prefix to define a private propertyNote: Code run in the Chrome console can access private properties outside the class. This is a DevTools-only relaxation of the JavaScript syntax restriction.
- How does JavaScript’s object creation differ from a language like Java or Ruby?
- In Java, object creation need a blueprint called the
Class
- Where as in JavaScript the creation of object doesn’t need any blueprint and objects can be created just like that. They do follow a
prototypal inheritance
which can be used to wire up different objects.
- In Java, object creation need a blueprint called the
- “losing
this
" - Making bound methods with class fields - link - We lose reference to
this
when a object method is passed elsewhere & called in another context, - example
class Button {
constructor(value) {
this.value = value;
}
click() {
alert(this.value);
}
}
let button = new Button("hello");
setTimeout(button.click, 1000); // undefined - So we need to either need to bind it
this.click = this.click.bind(this);
- or Pass a wrapper-function, such as
setTimeout(() => button.click(), 1000)
- or even better - link
Because a class's body has a
this
context, arrow functions as class fields close over the class'sthis
context, and thethis
inside the arrow function's body will correctly point to the instance (or the class itself, for static fields). However, because it is a closure, not the function's own binding, the value ofthis
will not change based on the execution context.click = () => {
alert(this.value);
}
- example
- We lose reference to
- static property
- static properties are the fields/methods which cannot be accessed on instances of the class. They can only be accessed via the class directly.
- we can define a private property using
#privateField
class ClassWithPrivate {
#privateField;
#privateFieldWithInitializer = 42;
#privateMethod() {
// …
}
static #privateStaticField;
static #privateStaticFieldWithInitializer = 42;
static #privateStaticMethod() {
// …
}
}Composition over Inheritance - link
- The problem w inheritance is that it encourages you to predict the future & once we’re into the inheritance there’s no turning back.
- Things that are not used also come along when inheritance is used
- Composition is more flexible