未分类

es2017

New Object Extensions
In this section, we will introduce three Object methods:

Object.entries,
Object.values,
Object.getOwnPropertyDescriptors.
Object.entries and Object.values
We already know Object.keys:

let account = {
first: ‘Zsolt’,
last: ‘Nagy’,
email: 'info@zsoltnagy.eu
};

Object.keys( account );

[“first”, “last”, “email”]

1
2
3
4
5
6
7
8
9
10

let account = {
first: ‘Zsolt’,
last: ‘Nagy’,
email: 'info@zsoltnagy.eu
};

Object.keys( account );

[“first”, “last”, “email”]

In ES7, Object.values and Object.entries are also available:

Object.values( account )

[“Zsolt”, “Nagy”, “info@zsoltnagy.eu“]

Object.entries( account )

[ [“first”, “Zsolt”],
[“last”, “Nagy”],
[“email”, “info@zsoltnagy.eu“] ]

1
2
3
4
5
6
7
8
9

Object.values( account )

[“Zsolt”, “Nagy”, “info@zsoltnagy.eu“]

Object.entries( account )

[ [“first”, “Zsolt”],
[“last”, “Nagy”],
[“email”, “info@zsoltnagy.eu“] ]

Object.entries can also be used for creating maps.

let accountMap = new Map( Object.entries( account ) );

Map {
“first” => “Zsolt”,
“last” => “Nagy”,
“email” => “info@zsoltnagy.eu
}

1
2
3
4
5
6
7
8

let accountMap = new Map( Object.entries( account ) );

Map {
“first” => “Zsolt”,
“last” => “Nagy”,
“email” => “info@zsoltnagy.eu
}

Symbol keys are ignored from the keys, values, and entries arrays.

The entries method was already defined for arrays in ES6, and it returned an ArrayIterator.

let iterator = Object.values( account ).entries();

ArrayIterator {}

console.log( iterator.next() );

{ value: [0, “Zsolt”], done: false }

for ( let [val, key] of iterator ) {
console.log( val, key );
}

1 “Nagy”
2 “info@zsoltnagy.eu

1
2
3
4
5
6
7
8
9
10
11
12
13

let iterator = Object.values( account ).entries();

ArrayIterator {}

console.log( iterator.next() );

{ value: [0, “Zsolt”], done: false }

for ( let [val, key] of iterator ) {
console.log( val, key );
}

1 “Nagy”
2 “info@zsoltnagy.eu

Object.getOwnPropertyDescriptors
Object.getOwnPropertyDescriptors returns all property descriptors of its first argument:

let player = {
cards: [ ‘Ah’, ‘Qc’ ],
chips: 1000
};

let descriptors =
Object.getOwnPropertyDescriptors( player );

console.log( descriptors );

Object {cards: Object, chips: Object}

console.log( descriptors.cards );

Object {
value: Array[2],
writable: true,
enumerable: true,
configurable: true
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

let player = {
cards: [ ‘Ah’, ‘Qc’ ],
chips: 1000
};

let descriptors =
Object.getOwnPropertyDescriptors( player );

console.log( descriptors );

Object {cards: Object, chips: Object}

console.log( descriptors.cards );

Object {
value: Array[2],
writable: true,
enumerable: true,
configurable: true
}

Object.getOwnPropertyDescriptors returns all property descriptors in an object with the same keys as the keys of the original object. The following four property descriptors are returned (source: developer.mozilla.com):

value: the value of the property
writable: true if and only if the value associated with the property may be changed (data descriptors only)
get: A function which serves as a getter for the property, or undefined if there is no getter (accessor descriptors only)
set: A function which serves as a setter for the property, or undefined if there is no setter (accessor descriptors only)
configurable: true if and only if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object
enumerable: true if and only if this property shows up during enumeration of the properties on the corresponding object
Let’s construct an example for getters and setters

let player = {
cards: [ ‘Ah’, ‘Qc’ ],
chips: 1000,
flop: [ ‘7d’, ‘7c’, ‘2c’ ],
get hand() {
return [ …this.cards, …this.flop ];
},
set hand( newHand ) {
if ( newHand.length && newHand.length === 5 ) {
[ this.cards[0],
this.cards[1],
…this.flop
] = newHand;
}
}
};

let descriptors =
Object.getOwnPropertyDescriptors( player );

console.log( descriptors );

Object {
cards: Object,
chips: Object,
flop: Object,
hand: Object
}

console.log( Object.keys( descriptors.hand ) );

[“get”, “set”, “enumerable”, “configurable”]

descriptors.hand.get

function get hand() {
return [ …this.cards, …this.flop ];
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

let player = {
cards: [ ‘Ah’, ‘Qc’ ],
chips: 1000,
flop: [ ‘7d’, ‘7c’, ‘2c’ ],
get hand() {
return [ …this.cards, …this.flop ];
},
set hand( newHand ) {
if ( newHand.length && newHand.length === 5 ) {
[ this.cards[0],
this.cards[1],
…this.flop
] = newHand;
}
}
};

let descriptors =
Object.getOwnPropertyDescriptors( player );

console.log( descriptors );

Object {
cards: Object,
chips: Object,
flop: Object,
hand: Object
}

console.log( Object.keys( descriptors.hand ) );

[“get”, “set”, “enumerable”, “configurable”]

descriptors.hand.get

function get hand() {
return [ …this.cards, …this.flop ];
}

Object.getOwnPropertyDescriptors handles String keys as well as Symbol keys[nodejssymbolshow]:

[nodejssymbolshow]: in order to show Symbol keys in node and in some browsers, instead of console.log, use console.dir with the flag showHidden: true. Check out this node issue for more information, or re-read the (relevant section) of Chapter 9.

let s = Symbol(‘test’);
let test = {
[s]: ‘test’
};

console.log( Object.getOwnPropertyDescriptors( test ) );

{ Symbol(test): Object {
configurable : true
enumerable : true
value : “test”
writable : true
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

let s = Symbol(‘test’);
let test = {
[s]: ‘test’
};

console.log( Object.getOwnPropertyDescriptors( test ) );

{ Symbol(test): Object {
configurable : true
enumerable : true
value : “test”
writable : true
}
}

As a consequence, Object.getOwnPropertyDescriptors can be used to make shallow copies of objects using Object.create.

Object.create takes two arguments:

the prototype of the object we wish to clone,
the property descriptors of the object.
In order to illustrate the difference between a shallow copy and a deep copy, let’s create a shallow copy of the player object defined above.

let player = {
cards: [ ‘Ah’, ‘Qc’ ],
chips: 1000,
flop: [ ‘7d’, ‘7c’, ‘2c’ ],
get hand() {
return [ …this.cards, …this.flop ];
},
set hand( newHand ) {
if ( newHand.length && newHand.length === 5 ) {
[ this.cards[0],
this.cards[1],
…this.flop
] = newHand;
}
}
};

let proto = Object.getPrototypeOf( player );
let descriptors =
Object.getOwnPropertyDescriptors( player );

let newPlayer = Object.create( proto, descriptors );

newPlayer.chips = 1500;

console.log( player.chips, newPlayer.chips );

1000 1500

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

let player = {
cards: [ ‘Ah’, ‘Qc’ ],
chips: 1000,
flop: [ ‘7d’, ‘7c’, ‘2c’ ],
get hand() {
return [ …this.cards, …this.flop ];
},
set hand( newHand ) {
if ( newHand.length && newHand.length === 5 ) {
[ this.cards[0],
this.cards[1],
…this.flop
] = newHand;
}
}
};

let proto = Object.getPrototypeOf( player );
let descriptors =
Object.getOwnPropertyDescriptors( player );

let newPlayer = Object.create( proto, descriptors );

newPlayer.chips = 1500;

console.log( player.chips, newPlayer.chips );

1000 1500

We have created two seemingly independent entities. However, when trying to change a card of the new player, the change will be made in the context of the old player as well.

newPlayer.cards[1] = ‘Ad’;

console.log( newPlayer.cards[1], player.cards[1] );

‘Ad’ ‘Ad’

1
2
3
4
5
6

newPlayer.cards[1] = ‘Ad’;

console.log( newPlayer.cards[1], player.cards[1] );

‘Ad’ ‘Ad’

This is because shallow copying only copied the reference of the cards array to the new player object. The original and the copied reference point at the exact same array.

New String Extensions
This section is about two String prototype extensions:

padStart,
padEnd.
These two methods are not yet implemented in all browsers. You need to open the Firefox developer tools or Chrome 57 to experiment with them.

Padding is used to add additional characters to the start or the end of a string so that it reaches a given size.

Padding is useful in character mode for alignment.

In the following example, let’s format the amounts such that the integer part contains 6 characters, and the fractional part contains 2 characters. Let’s pad the characters in front of the interger part with spaces, and the decimal part with zeros.

Let’s console log the result.

let amounts = [
‘1234.0’,
‘1’,
‘2.56’
];

console.log( |dddddd.ff| );
for ( let amount of amounts ) {
let [ front, back = ‘’ ] = amount.split(‘.’);
front = front.padStart( 6 );
back = back.padEnd( 2, ‘0’ );
console.log( |${front}.${back}| );
}

|dddddd.ff|
| 1234.00|
| 1.00|
| 2.56|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

let amounts = [
‘1234.0’,
‘1’,
‘2.56’
];

console.log( |dddddd.ff| );
for ( let amount of amounts ) {
let [ front, back = ‘’ ] = amount.split(‘.’);
front = front.padStart( 6 );
back = back.padEnd( 2, ‘0’ );
console.log( |${front}.${back}| );
}

|dddddd.ff|
| 1234.00|
| 1.00|
| 2.56|

If the second argument of padStart or padEnd is not given, ‘ ‘ characters will be used by default.

If you are interested in similar articles, sign up for weekly email updates below:

分享到