Last active
August 29, 2022 06:19
-
-
Save OleksiyRudenko/672d39b08d9d0da4e179aca49876c58b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// based on parts of: http://exploringjs.com/es6/ch_classes.html | |
const methodName = 'myMethod'; // for computed method names | |
// class | |
class Point { | |
// publicProperty = defaultValue; // NB! Unsupported yet? No assignment - no property! | |
publicProperty = 1; // need no constructor if it is only to initialize class properties | |
constructor(x, y) { | |
this.x = x; | |
this.y = y; | |
this._privateProperty = 0; // though it's a naming convention only | |
} | |
; // OK, ignored; other delimiters forbidden | |
handleChange = (e) => e.target; // bound to `this` | |
handleClick = ({target}) => target; // bound to `this` | |
toString() { // prototypical method | |
return `(${this.x}, ${this.y})`; | |
} | |
getConstructorName() { | |
return this.constructor.name; // Point or child class name | |
} | |
static staticMethod() { // static; inheritable | |
return this.name; // not this.constructor.name since this method is static | |
} | |
static get ZERO() { // static getter; see also approach of assigning static property below | |
return new Point(0, 0); | |
} | |
// getter & setters; used as obj.prop | |
get coords() { return [this.x, this.y]; } | |
set coords(coords) { [this.x, this.y] = coords; } | |
// computed method names | |
['my'+'Method']() {} | |
[methodName]() {} // see const above class def | |
// private data: http://exploringjs.com/es6/ch_classes.html#sec_private-data-for-classes | |
// 1. scoping | |
// 2. naming convention | |
// 3. WeakMap | |
// 4. Symbol | |
// other | |
logStaticProp() { | |
Point.ZERO(); // employ inner name | |
} | |
} | |
Point.ZERO = new Point(0,0); // static property | |
// Read-only property | |
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty | |
// (what about class level static?) | |
obj = Object.defineProperty(obj, prop, descriptor); // descriptor - as per link above | |
// subclass | |
class ColorPoint extends Point { | |
constructor(x, y, color) { | |
super(x,y); // call super() and call it before using `this` | |
this.color = color; | |
} | |
/* | |
Default constructor for derived class: | |
constructor(...args) { | |
super(...args); | |
} | |
*/ | |
toString() { | |
return super.toString() + ' in ' + this.color; | |
} | |
static staticMethod() { // extend/replace static methods | |
return 'both of types ' + this.name + ' and ' + super.staticMethod(); | |
} | |
} | |
// see more classes after next section | |
// usage | |
// you cannot call fn that uses class before class defined | |
const cp = new ColorPoint(25, 8, 'green'); | |
cp.toString(); | |
cp instanceof ColorPoint; // true | |
cp instanceof Point; // true | |
Object.getPrototypeOf(ColorPoint) == Point; // true | |
typeof Point; // 'function' | |
Point(); // ERROR! TypeError: Classes can’t be function-called | |
Point.staticMethod(); | |
// anonymous class expression | |
const myClassA = class { | |
// ... | |
}; | |
const instA = new MyClassA(); | |
// named class where class name is visible only inside it | |
const myClassB = class Me { | |
getClassName() { | |
return Me.name; | |
} | |
}; | |
const instB = new MyClassB(); | |
inst.getClassName(); // Me | |
Me.name; // ReferenceError: Me is not defined | |
// special methods | |
class IterableArguments { | |
constructor (...args) { | |
this.args = args; | |
} | |
// make class iterable (via for-of loops etc) | |
[Symbol.iterator]() { | |
} | |
// generator | |
* [Symbol.iterator]() { | |
for (const arg of this.args) { | |
yield arg; | |
} | |
} | |
} | |
// usage | |
for (const x of new IterableArguments('hello','world')) { | |
console.log(x); | |
} | |
// special extensions - Exception Class | |
class MyError extends Error { | |
} | |
throw new MyError('Smth happened!'); | |
// special arrays | |
// Note that subclassing Array is usually not the best solution. | |
// It’s often better to create your own class (whose interface you control) | |
// and to delegate to an Array in a private property. | |
class Stack extends Array { | |
get top() { | |
return this[this.length - 1]; | |
} | |
} | |
var stack = new Stack(); | |
stack.push(1); | |
stack.push(2); | |
stack.top; // 2 | |
stack.length; // 2 | |
// Multiple inheritance | |
class Person {} | |
class Storage { save(db){} } | |
class Validation { validate(schema){} } | |
class Employee extends Storage, Validation, Person { } // Error! | |
class Person {} | |
const Storage = Sup => class extends Sup { | |
save(database) { } | |
}; | |
const Validation = Sup => class extends Sup { | |
validate(schema) { } | |
}; | |
class Employee extends Storage(Validation(Person)) { | |
} | |
// Function.prototype.apply() === | |
function instantiate(TheClass, args) { | |
return new TheClass(...args); | |
} | |
// or | |
function instantiate(TheClass, args) { | |
return Reflect.construct(TheClass, args); | |
} | |
/* =================================== further reading =============== | |
http://exploringjs.com/es6/ch_classes.html#sec_private-data-for-classes | |
https://github.com/rwaldron/tc39-notes/blob/master/es6/2015-01/jan2015-allen-slides.pdf | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// class | |
class Point { | |
constructor(x, y) { | |
this.x = x; | |
this.y = y; | |
} | |
toString() { | |
return `(${this.x}, ${this.y})`; | |
} | |
static staticMethod() { | |
return Point.name; | |
} | |
static get ZERO() { | |
return new Point(0, 0); | |
} | |
get coords() { return `(${this.x}, ${this.y})`; } | |
set coords(coords) { this.x = coords[0]; this.y = coords[1]; } | |
getConstructorName() { return this.constructor.name; } | |
} | |
class ColorPoint extends Point { | |
constructor(x, y, color) { | |
super(x, y); | |
this.color = color; | |
} | |
toString() { | |
return super.toString() + ' in ' + this.color; | |
} | |
static staticMethod() { | |
return 'both of types ' + this.name + ' and ' + super.staticMethod(); | |
} | |
} | |
const p = new Point(1, 3); | |
const cp = new ColorPoint(25, 8, 'green'); | |
[p, cp, Object.keys(cp)].forEach(console.dir); | |
/* | |
// Below are only relevant properties from console.dir output. | |
// Repeating content of objects replaced with {{ObjectName}} notation. | |
// Getters are resolved. | |
Point | |
x: 1 | |
y: 3 | |
coords: "(1, 3)" | |
__proto__: | |
constructor: class Point | |
ZERO: Point | |
arguments: (...) | |
caller: (...) | |
length: 2 | |
name: "Point" | |
prototype: | |
constructor: class Point {{class Point}} | |
coords: "(undefined, undefined)" | |
getConstructorName: ƒ getConstructorName() | |
toString: ƒ toString() | |
get coords: ƒ coords() | |
set coords: ƒ coords(coords) | |
staticMethod: ƒ staticMethod() | |
get ZERO: ƒ ZERO() | |
coords: "(1, 3)" | |
getConstructorName: ƒ getConstructorName() | |
toString: ƒ toString() | |
get coords: ƒ coords() | |
set coords: ƒ coords(coords) | |
ColorPoint | |
color: "green" | |
x: 25 | |
y: 8 | |
coords: "(25, 8)" | |
__proto__: Point | |
constructor: class ColorPoint | |
ZERO: Point | |
arguments: (...) | |
caller: (...) | |
length: 3 | |
name: "ColorPoint" | |
prototype: Point {constructor: ƒ, toString: ƒ} | |
constructor: class ColorPoint | |
ZERO: Point | |
arguments: (...) | |
caller: (...) | |
length: 3 | |
name: "ColorPoint" | |
prototype: Point {constructor: ƒ, toString: ƒ} | |
constructor: class ColorPoint {{class ColorPoint}} | |
coords: (...) | |
toString: ƒ toString() | |
__proto__: | |
constructor: class Point {{class Point}} | |
coords: "(undefined, undefined)" | |
getConstructorName: ƒ getConstructorName() | |
toString: ƒ toString() | |
get coords: ƒ coords() | |
set coords: ƒ coords(coords) | |
staticMethod: ƒ staticMethod() | |
__proto__: class Point | |
ZERO: Point | |
arguments: (...) | |
caller: (...) | |
length: 2 | |
name: "Point" | |
prototype: {constructor: {{class Point}}, toString: ƒ, getConstructorName: ƒ} | |
staticMethod: ƒ staticMethod() | |
get ZERO: ƒ ZERO() | |
coords: "(undefined, undefined)" | |
toString: ƒ toString() | |
__proto__: Object | |
constructor: class Point {{class Point}} | |
coords: "(undefined, undefined)" | |
getConstructorName: ƒ getConstructorName() | |
toString: ƒ toString() | |
get coords: ƒ coords() | |
set coords: ƒ coords(coords) | |
staticMethod: ƒ staticMethod() | |
__proto__: class Point | |
ZERO: Point | |
arguments: (...) | |
caller: (...) | |
length: 2 | |
name: "Point" | |
prototype: {constructor: {{class Point}}, toString: ƒ, getConstructorName: ƒ} | |
staticMethod: ƒ staticMethod() | |
get ZERO: ƒ ZERO() | |
coords: "(25, 8)" | |
toString: ƒ toString() | |
__proto__: Object | |
constructor: class Point {{class Point}} | |
coords: "(25, 8)" | |
getConstructorName: ƒ getConstructorName() | |
toString: ƒ toString() | |
get coords: ƒ coords() | |
set coords: ƒ coords(coords) | |
// Object.keys() lists only own iterable properties | |
Object.keys(cp) => Array(3) | |
0: "x" // what?! own property? | |
1: "y" // what?! own property? | |
2: "color" | |
length: 3 | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://babeljs.io/docs/en/babel-plugin-proposal-class-properties