You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
> **Best Practice**: While the syntax for creating classes in ES6 obscure how implementation and prototypes work under the hood, it is a good feature for beginners and allows us to write cleaner code.
520
+
521
+
## Symbols
522
+
523
+
Symbols have existed prior to ES6, but now we have a public interface to using them directly. One such example is to create unique property keys which will never collide:
524
+
525
+
```javascript
526
+
constkey=Symbol();
527
+
constkeyTwo=Symbol();
528
+
constobject= {};
529
+
530
+
object.key='Such magic.';
531
+
object.keyTwo='Much Uniqueness'
532
+
533
+
// Two Symbols will never have the same value
534
+
>> key === keyTwo
535
+
>>false
536
+
```
537
+
538
+
## Maps
539
+
540
+
**Maps** is a much needed data structure in JavaScript. Prior to ES6, we created **hash** maps through objects:
541
+
542
+
```javascript
543
+
var map =newObject();
544
+
map[key1] ='value1';
545
+
map[key2] ='value2';
546
+
```
547
+
548
+
However, this does not protect us from accidentally overriding functions with specific property names:
>TypeError: Propery 'hasOwnProperty' is not a function
553
+
```
554
+
555
+
Actual **Maps** allow us to **set**, **get** and **search** for values (andmuchmore).
556
+
557
+
```javascript
558
+
let map = new Map();
559
+
> map.set('name', 'david');
560
+
> map.get('name'); // david
561
+
> map.has('name'); // true
562
+
```
563
+
564
+
The most amazing part of Maps is that we are no longer limited to just using strings. We can now use any type as a key, and it will not be type-casted to a string.
565
+
566
+
```javascript
567
+
let map = new Map([
568
+
['name', 'david'],
569
+
[true, 'false'],
570
+
[1, 'one'],
571
+
[{}, 'object'],
572
+
[function () {}, 'function']
573
+
]);
574
+
575
+
for (let key ofmap.keys()) {
576
+
console.log(typeof key);
577
+
// > string, boolean, number, object, function
578
+
};
579
+
```
580
+
581
+
We can also iterate over maps using **.entries( )**:
582
+
583
+
```javascript
584
+
for (let [key, value] ofmap.entries()) {
585
+
console.log(key, value);
586
+
}
587
+
```
588
+
589
+
## WeakMaps
590
+
591
+
In order to store private data in < ES5, we had various ways of doing this. One such method was using naming conventions:
592
+
593
+
```javascript
594
+
classPerson {
595
+
constructor(age) {
596
+
this._age= age;
597
+
}
598
+
599
+
_incrementAge() {
600
+
this._age+=1;
601
+
}
602
+
}
603
+
```
604
+
605
+
But naming conventions can cause confusion in a codebase and are not always going to be upheld. Instead, we can use WeakMaps to store our values:
606
+
607
+
```javascript
608
+
let _age =newWeakMap();
609
+
classPerson {
610
+
constructor(age) {
611
+
_age.set(this, age);
612
+
}
613
+
614
+
incrementAge() {
615
+
let age =_age.get(this);
616
+
if(age >50) {
617
+
console.log('Midlife crisis');
618
+
}
619
+
}
620
+
}
621
+
```
622
+
623
+
The cool thing about using WeakMaps to store our private data is that their keys do not give away the property names, which can be seen by using **Reflect.ownKeys()**:
624
+
625
+
```javascript
626
+
>constperson=newPerson(50);
627
+
>person.incrementAge(); // 'Midlife crisis'
628
+
>Reflect.ownKeys(person); // []
629
+
```
630
+
631
+
## Promises
632
+
633
+
Promises allow us to turn our horizontal code (callback hell):
634
+
635
+
```javascript
636
+
func1(function (value1) {
637
+
func2(value1, function(value2) {
638
+
func3(value2, function(value3) {
639
+
func4(value3, function(value4) {
640
+
func5(value4, function(value5) {
641
+
// Do something with value 5
642
+
});
643
+
});
644
+
});
645
+
});
646
+
});
647
+
```
648
+
649
+
Into vertical code:
650
+
651
+
```javascript
652
+
func1(value1)
653
+
.then(func2(value1) { })
654
+
.then(func3(value2) { })
655
+
.then(func4(value3) { })
656
+
.then(func5(value4) {
657
+
// Do something with value 5
658
+
});
659
+
```
660
+
661
+
Prior to ES6, we used [bluebird](https://github.com/petkaantonov/bluebird) or [Q](https://github.com/kriskowal/q). Now we have Promises natively:
662
+
663
+
```javascript
664
+
newPromise((resolve, reject) =>
665
+
reject(newError('Failed to fufill Promise')))
666
+
.catch(reason=>console.log(reason));
667
+
```
668
+
669
+
Where we have two handlers, **resolve** (a function called when the Promise is **fufilled**) and **rejected** (a function called when the Promise is **rejected**).
670
+
671
+
> **Benefits of Promises**: Error Handling using a bunch of nested callbacks can get chaotic. Using Promises, we have a clear path to bubbling errors up and handling them appropriately. Moreover, the value of a Promise after it has been resolved/rejected is immutable - it will never change.
0 commit comments