From 9564df47e62e60e504eb228cdb2e19fc562cdfab Mon Sep 17 00:00:00 2001 From: Aaron Nguyen Date: Tue, 1 Mar 2022 10:14:36 -0500 Subject: [PATCH] Done Chapter 8. Using Inheritance --- 8-using-inheritance/array-vs-string.js | 12 +++++ 8-using-inheritance/inherit-from-function.js | 7 +++ 8-using-inheritance/inheritance.js | 9 ++++ 8-using-inheritance/managing-instaces.js | 33 +++++++++++++ 8-using-inheritance/prototypal.js | 50 ++++++++++++++++++++ 8-using-inheritance/using-inheritance.md | 7 +++ 6 files changed, 118 insertions(+) create mode 100644 8-using-inheritance/array-vs-string.js create mode 100644 8-using-inheritance/inherit-from-function.js create mode 100644 8-using-inheritance/managing-instaces.js create mode 100644 8-using-inheritance/prototypal.js diff --git a/8-using-inheritance/array-vs-string.js b/8-using-inheritance/array-vs-string.js new file mode 100644 index 0000000..9735d65 --- /dev/null +++ b/8-using-inheritance/array-vs-string.js @@ -0,0 +1,12 @@ +class MyString extends String {} +class MyArray extends Array { + static get [Symbol.species]() { + return Array; + } +} + +const concString = new MyString().concat(new MyString()); +const concArray = new MyArray().concat(new MyArray()); + +console.log(`instanceof MyString?: ${concString instanceof MyString}`); +console.log(`instanceof MyArray?: ${concArray instanceof MyArray}`); diff --git a/8-using-inheritance/inherit-from-function.js b/8-using-inheritance/inherit-from-function.js new file mode 100644 index 0000000..2bd5c8b --- /dev/null +++ b/8-using-inheritance/inherit-from-function.js @@ -0,0 +1,7 @@ +function LegacyClass(value) { + this.value = value; +} + +class NewClass extends LegacyClass {} + +console.log(new NewClass(1)); diff --git a/8-using-inheritance/inheritance.js b/8-using-inheritance/inheritance.js index 625dd01..dea2bf3 100644 --- a/8-using-inheritance/inheritance.js +++ b/8-using-inheritance/inheritance.js @@ -17,6 +17,12 @@ class Person { } } +class AwesomePerson extends Person { + get fullName() { + return `Awesome ${super.fullName}`; + } +} + class ReputablePerson extends Person { constructor(firstName, lastName, rating) { super(firstName, lastName); @@ -33,3 +39,6 @@ class ReputablePerson extends Person { const alan = new ReputablePerson("Alan", "Turing", 5); console.log(alan.toString()); console.log(alan.fullName); + +const ball = new AwesomePerson("Lucille", "Ball"); +console.log(ball.fullName); diff --git a/8-using-inheritance/managing-instaces.js b/8-using-inheritance/managing-instaces.js new file mode 100644 index 0000000..4452202 --- /dev/null +++ b/8-using-inheritance/managing-instaces.js @@ -0,0 +1,33 @@ +class Names { + constructor(...names) { + this.names = names; + } + + filter1(selector) { + return new Names(...this.names.filter(selector)); + } + + filter2(selector) { + const constructor = Reflect.getPrototypeOf(this).constructor; + return new constructor(...this.names.filter(selector)); + } + + filter3(selector) { + const constructor = + Reflect.getPrototypeOf(this).constructor[Symbol.species] || + Reflect.getPrototypeOf(this).constructor; + + return new constructor(...this.names.filter(selector)); + } +} + +class SpecializedNames extends Names { + static get [Symbol.species]() { + return Names; + } +} + +const specializedNames = new SpecializedNames("Java", "C#", "JavaScript"); +console.log(specializedNames.filter1((name) => name.startsWith("Java"))); +console.log(specializedNames.filter2((name) => name.startsWith("Java"))); +console.log(specializedNames.filter3((name) => name.startsWith("Java"))); diff --git a/8-using-inheritance/prototypal.js b/8-using-inheritance/prototypal.js new file mode 100644 index 0000000..3c77239 --- /dev/null +++ b/8-using-inheritance/prototypal.js @@ -0,0 +1,50 @@ +class Person { + constructor(firstName, lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + toString() { + return `Name: ${this.firstName} ${this.lastName}`; + } + get fullName() { + return `${this.firstName} ${this.lastName}`; + } + get lastName() { + return this._lastName; + } + set lastName(value) { + this._lastName = value; + } +} + +class ReputablePerson extends Person { + constructor(firstName, lastName, rating) { + super(firstName, lastName); + this.rating = rating; + } + toString() { + return `${super.toString()} Rating: ${this.rating}`; + } + get fullName() { + return `Reputed ${this.lastName}, ${super.fullName}`; + } +} + +const printPrototypeHierarchy = function (instance) { + if (instance !== null) { + console.log(instance); + printPrototypeHierarchy(Reflect.getPrototypeOf(instance)); + } +}; + +const alan = new ReputablePerson("Alan", "Turing", 5); +printPrototypeHierarchy(alan); + +class ComputerWiz {} + +Reflect.setPrototypeOf(Reflect.getPrototypeOf(alan), ComputerWiz.prototype); +console.log("...after change of prototpye..."); +printPrototypeHierarchy(alan); + +const ada = new ReputablePerson("Ada", "Lovelace", 5); +printPrototypeHierarchy(ada); diff --git a/8-using-inheritance/using-inheritance.md b/8-using-inheritance/using-inheritance.md index 44d47cb..cd460a0 100644 --- a/8-using-inheritance/using-inheritance.md +++ b/8-using-inheritance/using-inheritance.md @@ -23,3 +23,10 @@ JavaScript implements **prototypal** inheritance - Extending a class - Overriding methods +- `extends` implies prototypal inheritance + - `object.prototype` is different from `Reflect.getPrototypeOf(object)` https://stackoverflow.com/q/38740610 + - `object.prototype` is instance's prototype. `Reflect.getPrototypeOf(object)` is prototype of **instance's parent** +- Changing the prototype chain using `Reflect.setPrototypeOf()` +- Using default constructors +- Extending legacy classes +- Managing instance types with species