Classes, Symbols, Objects, and Decorations
class
-
Use of classes
// Declaration of class class Fruit { } // Equivalent to the declaration of a constructor function Fruit() { }
Note: Class declarations differ from constructor declarations: Class declarations are not scoped ahead of time
-
Properties and methods of classes
-
Constructor method: the constructor method is called automatically when the class is instantiated, and the parameters for instantiation are received by the constructor method
class Log { constructor(...args) { console.log(args); } } new Log('a', 'b', 'c') // ['a', 'b', 'c']
-
get keyword
class Counter { constructor(start) { this.count = start; } get next() { return this.count++ } } // get next(){}:get keyword modifies a method to indicate that the Counter instance will have a next property. Accessing this property will return the result of the method call const counter = new Counter(2); console.log(counter.next); // 2 console.log(counter.next); // 3 console.log(counter.next); // 4
-
Set keyword: The set keyword modifies a method that indicates when a LocalStorage instance sets the data property. Setting this property returns the result of the method call
class LocalStorage { constructor(key) { this.key = key; } get data() { return JSON.parse(localStorage.getItem(this.key)); } set data(data) { localStorage.setItem(this.key, JSON.stringify(data)); } } const ls = new LocalStorage('groceries'); ls.data = ['apples', 'bananas', 'grapes'] console.log(ls.data); // ['apples', 'bananas', 'grapes']
-
static keyword
-
The static keyword modifier means that this method is static.
-
The static keyword modifies other keywords. static get\static set indicates that it is a static property accessor
-
Note that class has no static properties, only static methods.
class MathHelper { static sum(...numbers) { return numbers.reduce((a,b) => a+b) } } console.log(MathHelper.sum(1,2,3,4,5)); // 15
-
-
-
Class inheritance: keyword extends
Call super in the constructor function. Inheritance of the parent class can be achieved. Parameters accepted in super are passed to the constructor or class of the parent class. Methods in the parent class can also be called as super.method names.
class Fruit { constructor(type, weight) { this.type = type; this.weight = weight; } chop() { console.log(this.type, this.weight); } } class Banana extends Fruit { constructor() { super('banana', 105); } slice(){ this.pieces = 12; super.chop(); return 111 } } const banana = new Banana(); banana.slice() // banana 105
Symbol
Symbols are a new basic value type added by ES and a data type in JS 7.
-
Local Symbols
-
Use of symbols
const first = Symbol()
-
Add a description or description when creating symbols
const first = Symbol('my first')
-
Symbols are unique, even if they are created with the same description
Symbol('my first') === Symbol('my first') /// false
-
typeof symbol
typeof Symbol('my first') // symbol
-
Symbols can be used as attribute names for objects, and when accessing their corresponding values, they must use the same symbol
const weapon = Symbol('weapon'); const character = { name: 'Penguin', [weapon]: 'umbrella', } console.log(Object.getOwnPropertySymbols(character[weapon]); // 'umbrella'
-
Traditional methods [for...in, Object.keys, Object.getOwnPropertyNames] cannot get the property name of a symbol type when reading the property name from an object.
-
Gets the symbol value used as the property name in the object: Object.getOwnPropertySymbols
const weapon = Symbol('weapon'); const character = { name: 'Penguin', [weapon]: 'umbrella', } console.log(Object.getOwnPropertySymbols(character)); // [Symbol(weapon)]
-
-
Practical use of symbols
JavaScript libraries can use the ** symbol ** to map objects to DOM elements. Previous method: add an attribute to the DOM element that points to the API, but that will pollute the DOM element. Also be careful if other libraries use this attribute, otherwise conflicts will occur.
The advantage of using the ** symbol ** is that the symbol is unique, does not have to worry about contaminating DOM elements, is unique, and does not have to worry about conflicts with other libraries.
// Returns if the el element has a calendar API. If it does not, assigns the el element a calendar API function createCalendar(el) { if(cache in el) { // Detecting whether the Symbol value cache exists in the el element return el[cache] // Use cache directly to avoid re-instantiation } const api = el[cache] = { // Write a calendar API here } return api }
Built-in improvements to objects
-
Extend the object with Object.assign: using Object.assign(target,... source); each source copies its own value into the target. In order not to affect the original target object, the target is usually set to {}. Therefore, the use of Object.assign is
Object.assign({}, source1, source2,[...source3]);
-
Object. setProtorypeOf, sets the prototype of an object
const baseCat = {type: 'cat', legs: 4}; const cat = Object.create(baseCat); // cat: {}, prototype is baseCat. An empty object is created and a prototype is specified for it. cat.name = 'Milanesita'; const baseCat = {type: 'cat', legs: 4}; const cat = Object.setPrototypeOf({name: 'Milanesita'}, baseCat); // Cat: {name:'Milanesita'}, prototype is baseCat. An object is created, assigned a value, and assigned a prototype. // Difference between the two: create can only specify a prototype for a new object when it is created. setPrototypeOf can change the prototype of any object