Skip to Content

Built-ins

Symbols

  • A symbol is a unique and immutable data type that is often used to identify object properties.
  • To create a symbol, write Symbol() with an optional string as its description.
const sym1 = Symbol('apple'); console.log(sym1); // Symbol(apple)

Uniqueness

  • Each time a new symbol is created, regardless of the description.
  • The description is only used to describe the symbol. It’s not used as part of the symbol itself.
const sym2 = Symbol('banana'); const sym3 = Symbol('banana'); console.log(sym2 === sym3); // false

Use case

  • It is most often used to uniquely identify properties within an object.
// use string as property keys, and the // second banana overwrites the first one const bowl = { 'apple': { color: 'red', weight: 136.078 }, 'banana': { color: 'yellow', weight: 183.151 }, 'orange': { color: 'orange', weight: 170.097 }, 'banana': { color: 'yellow', weight: 176.845 } }; // use symbol as property keys, // and each symbol is unique const bowl = { [Symbol('apple')]: { color: 'red', weight: 136.078 }, [Symbol('banana')]: { color: 'yellow', weight: 183.15 }, [Symbol('orange')]: { color: 'orange', weight: 170.097 }, [Symbol('banana')]: { color: 'yellow', weight: 176.845 } };

Set

  • Sets are not indexed-based.
  • Items in a Set cannot be accessed individually.
// create const set1 = new Set() const set2 = new Set(array) // modify set1.add(element); // return the set itself set2.delete(element); // return true or false // delete set1.clear(); // check length set1.size; // check element existence set2.has(element); // retrieve all values const iterator1 = set1.keys(); // return a SetIterator const iterator2 = set1.values(); // return a SetIterator

WeakSet

  • A normal Set with the following differences:
    • WeakSet only contains objects.
    • Not iterable and thus cannot be looped over.
    • Does not have a .clear() method.
  • When an object is deleted, it will also be deleted from the WeakSet when garbage collection runs.
  • WeakSet is useful when there needs an efficient, lightweight solution for creating groups of objects.

Map

  • Both the keys and the values can be objects, primitive values, or a combination of the two.
const map = new Map(); map.set(key, value); // return the map itself map.get(key); map.delete(key); // return true or false map.clear(); map.has(key);

Looping through Map

  • Default MapIterator
const iterator1 = map.keys(); iterator1.next(); const iterator2 = map.values(); iterator2.next();
  • for...of loop
for (const [key, value] of map) { // ... }
  • forEach loop
map.forEach((value, key) => fn(value, key));

WeakMap

  • A normal Map with the following differences:
    • Only contain objects as keys.
    • Not iterable.
    • Does not have a .clear() method.
  • When an object is deleted, the object key will also be deleted from the WeakMap when garbage collection runs.

Promises

  • A promise will start some work that will be done asynchronously.

  • A Promise constructor takes a function with two functions.

    • When the promise succeeds, the resolve function will be called.
    • When the promise fails, the reject function will be called.
  • A promise returns immediately.

  • The promise object has a .then() method that takes in the resolve and reject functions.

const promise = new Promise(function (resolve, reject) { if (successful) { resolve(arguments); } else { reject('Promise failed'); } }); promise.then((params) => { console.log(`Succeed: ${params}`); }, (errorMessage) => { console.log(errorMessage); });

Proxies

  • Proxy constructor takes in two items:
    • The object to be proxied.
    • The proxy handler object.
      • It contains the list of methods it will handle for the proxied object.
  • Pass through proxy
    • new Proxy(object, {})
    • It just passes the request directly to the source object.

get trap

  • Intercept calls to properties.
  • Take over whenever any property on the proxy is accessed.
const richard = {status: 'looking for work'}; const handler = { /** * @param target the proxied object (richard) * @param propName the name of the property being accessed (status) */ get(target, propName) { return target[propName]; } }; const agent = new Proxy(richard, handler);

set trap

  • Intercepting code that will change a property.
const richard = {status: 'looking for work'}; const handler = { /** * @param target the proxied object (richard) * @param propName the name of the property being modified (payRate) * @param value the new value to be set to propName (payRate) */ set(target, propName, value) { // if the pay is being set, take 15% as commission if (propName === 'payRate') { value = value * 0.85; } target[propName] = value; } }; const agent = new Proxy(richard, handler);

All traps

  • get trap: handle calls to property access.
  • set trap: handle setting the property to a new value.
  • apply trap: handle being invoked (the object being proxied is a function).
  • has trap: handle the using in operator.
  • deleteProperty trap: handle if a property is deleted.
  • ownKeys trap: handle when all keys are requested.
  • construct trap: handle when the proxy is used with the new keyword as a constructor.
  • defineProperty trap: handle when defineProperty is used to create a new property on the object.
  • getOwnPropertyDescriptor trap: handle getting the property’s descriptors.
  • preventExtenions trap: handle calls to Object.preventExtensions() on the proxy object.
  • isExtensible trap: handle calls to Object.isExtensible on the proxy object.
  • getPrototypeOf trap: handle calls to Object.getPrototypeOf on the proxy object.
  • setPrototypeOf trap: handle calls to Object.setPrototypeOf on the proxy object.

Proxies vs ES5 getter / setter

  • With ES5’s getter and setter methods, you need to know before hand the properties that are going to be get/set.
  • With ES6 Proxies, we do not need to know the properties beforehand.
var obj = { _age: 5, _height: 4, get age() { console.log(`getting the "age" property`); console.log(this._age); }, get height() { console.log(`getting the "height" property`); console.log(this._height); } }; obj.age; // logs 'getting the "age" property' & 5 obj.height; // logs 'getting the "height" property' & 4

Generators

  • Use a generator to be able to pause a function mid-execution.
    • function* name() { ... }
  • The asterisk of the generator can be placed anywhere between the function keyword and the function name.
  • The community has coalesced into having the asterisk appear right next to the function keyword.
  • Generators cannot be defined with fat arrow functions.
  • Every call to next() will
    • Fulfill the previous yield expression if there is any;
    • Return the value following the next yield;
    • Pause at the same next yield statement.
function* foo() { console.log(`function starts`); // the first next() returns 123 and pause here const a = (yield 123); console.log(`a: ${a}`); // the second next(456) replace (yield 123) with 456, // and assign it to a, print out a's value, and pause here yield a; console.log(`function ends`); // the third next() will print out the statement, // and return undefined } const iterator = foo(); iterator.next(); // function starts // { value: 123, done: false } iterator.next(456); // a: 456 // { value: 456, done: false } iterator.next(); // function ends // { value: undefined, done: false }
最近更新: