ES6新特性(2015)

1. 数值的扩展

  • Number.isFinite() 用来检查一个数值是否为有限的(finite);如果参数类型不是数值,Number.isFinite一律返回false。

    Number.isFinite(15); // true
    Number.isFinite(NaN); // false
  • Number.isNaN()用来检查一个值是否为NaN。如果参数类型不是NaN,Number.isNaN一律返回false。

    Number.isNaN(NaN) // true
    Number.isNaN("NaN") // false
  • Number.parseInt()

  • Number.parseFloat()
  • Number.isInteger() 用来判断一个数值是否为整数。

    Number.isInteger(25) // true
    Number.isInteger(25.0) // true
    Number.isInteger(25.1) // false
  • Math.trunc() 方法用于去除一个数的小数部分,返回整数部分。

    Math.trunc(4.1) // 4
    Math.trunc(4.9) // 4
    Math.trunc(-4.1) // -4
    Math.trunc(-4.9) // -4
    Math.trunc(-0.1234) // -0
  • Math.sign() 方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值

  1. 参数为正数,返回+1;
  2. 参数为负数,返回-1;
  3. 参数为 0,返回0;
  4. 参数为-0,返回-0;
  5. 其他值,返回NaN。
Math.sign(-5) // -1
Math.sign(5) // +1
Math.sign(0) // +0
Math.sign(-0) // -0
Math.sign(NaN) // NaN
  • Math.cbrt() 方法用于计算一个数的立方根。
    Math.cbrt(-1) // -1
    Math.cbrt(0) // 0
    Math.cbrt(1) // 1
    Math.cbrt(2) // 1.2599210498948734


2. Symbol

原始数据类型Symbol,表示独一无二的值;它是 JavaScript 语言的第七种数据类型,

七中数据类型:

  • null
  • undefined
  • 布尔
  • 字符串
  • 对象
  • 数值
  • Symbol
Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述
let s1 = Symbol('foo');
let s2 = Symbol('bar');

s1 // Symbol(foo)
s2 // Symbol(bar)

s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"
作为属性名的 Symbol

对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。

let mySymbol = Symbol();

// 第一种写法
let a = {};
a[mySymbol] = 'Hello!';

// 第二种写法
let a = {
[mySymbol]: 'Hello!'
};

// 第三种写法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });

// 以上写法都得到同样结果
a[mySymbol] // "Hello!"

注意:Symbol 值作为对象属性名时,不能用点运算符。

const mySymbol = Symbol();
const a = {};

a.mySymbol = 'Hello!';
a[mySymbol] // undefined
a['mySymbol'] // "Hello!"

Symbol用法,例:

const shapeType = {
triangle: Symbol()
};

function getArea(shape, options) {
let area = 0;
switch (shape) {
case shapeType.triangle:
area = .5 * options.width * options.height;
break;
}
return area;
}

getArea(shapeType.triangle, { width: 100, height: 100 });


3. Set

Set 本身是一个构造函数,用来生成 Set 数据结构;成员的值都是唯一的,没有重复的值;向 Set 加入值的时候,不会发生类型转换,所以5和”5”是两个不同的值;

Set 内部判断两个值是否不同,使用的算法叫做“Same-value-zero equality”,它类似于精确相等运算符(===),主要的区别是NaN等于自身,而精确相等运算符认为NaN不等于自身。

set实例的属性和方法
  • Set.prototype.constructor:构造函数,默认就是Set函数。
  • Set.prototype.size:返回Set实例的成员总数。
const set=new Set([1,2,1])

set.size //2
  • add(value):添加某个值,返回 Set 结构本身。
  • delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
  • has(value):返回一个布尔值,表示该值是否为Set的成员。
  • clear():清除所有成员,没有返回值。
const set = new Set();

set.add(1).add(2);

set.size //2

set.has(1) //true

set.delete(1)

set.has(1) //false

set.clear()

Array.from方法可以将 Set 结构转为数组,并且会去除重复的数据。

const set = new Set([1,2,3]);

const array = Array.from(set); //[1,2,3]

这里还有一个简便的写法

const set = new Set([1,2,3]);

const array = [...set]; //[1,2,3]

遍历操作
  • keys():返回键名的遍历器
  • values():返回键值的遍历器
  • entries():返回键值对的遍历器
  • forEach():使用回调函数遍历每个成员

(1) keys方法、values方法、entries方法返回的都是遍历器对象

let set = new Set(['red', 'green', 'blue']);

for (let item of set.keys()) {
console.log(item);
}
// red
// green
// blue

for (let item of set.values()) {
console.log(item);
}
// red
// green
// blue

for (let item of set.entries()) {
console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]

set 结构的实例默认可遍历,它的默认遍历器生成函数就是它的values方法。可以省略values方法,直接用for…of循环遍历 Set。

let set = new Set(['red', 'green', 'blue']);

for (let x of set) {
console.log(x);
}
// red
// green
// blue

(2)forEach()
Set 结构的键名就是键值(两者是同一个值),因此第一个参数与第二个参数的值永远都是一样的。

set = new Set([1, 4, 9]);
set.forEach((value, key) => console.log(key + ' : ' + value))
// 1 : 1
// 4 : 4
// 9 : 9

数组的map和filter方法也可以间接用于 Set 了。

let set = new Set([1, 2, 3]);
set = new Set([...set].map(x => x * 2));
// 返回Set结构:{2, 4, 6}

let set = new Set([1, 2, 3, 4, 5]);
set = new Set([...set].filter(x => (x % 2) == 0));
// 返回Set结构:{2, 4}


4. Map

JavaScript 的对象(Object),但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

const m = new Map();
const o = {p: 'Hello World'};

m.set(o, 'content')
m.get(o) // "content"

map实例的属性和方法
  • size 属性

  • set(key, value) 如果key已经有值,则键值会被更新,否则就新生成该键。

  • get(key) 如果找不到key,返回undefined。
  • has(key)
  • delete(key) 删除某个键,返回true。如果删除失败,返回false。
  • clear()
const map = new Map();

map.set('edition', 6).set(1, 'a');

map.get(1) //'a'

map.has(1) //true

map.delete(1) //true

map.clear()
遍历操作
  • keys():返回键名的遍历器。
  • values():返回键值的遍历器。
  • entries():返回所有成员的遍历器。
  • forEach():遍历 Map 的所有成员。

Map 结构的默认遍历器接口(Symbol.iterator属性),就是entries方法。

与其他数据结构的互相转换

(1)Map 转为数组
Map 转为数组最方便的方法,就是使用扩展运算符(…)。

const myMap = new Map()
.set(true, 7)
.set({foo: 3}, ['abc']);
[...myMap]
// [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]

(2)数组 转为 Map
将数组传入 Map 构造函数,就可以转为 Map。

new Map([
[true, 7],
[{foo: 3}, ['abc']]
])
// Map {
// true => 7,
// Object {foo: 3} => ['abc']
// }

(3)Map 转为对象
如果所有 Map 的键都是字符串,它可以无损地转为对象。如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名

function strMapToObj(strMap) {
let obj = Object.create(null);
for (let [k,v] of strMap) {
obj[k] = v;
}
return obj;
}

const myMap = new Map()
.set('yes', true)
.set('no', false);
strMapToObj(myMap)
// { yes: true, no: false }

(4)对象转为 Map

function objToStrMap(obj) {
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
}

objToStrMap({yes: true, no: false})
// Map {"yes" => true, "no" => false}

(5)Map 转为 JSON

(6)JSON 转为 Map


ES7新特性(2016)

1.Array.prototype.includes()

includes() 函数用来判断一个数组是否包含一个指定的值,如果包含则返回 true,否则返回 false

let arr = ['react', 'angular', 'vue'];

if (arr.includes('react')) {
console.log('react存在');
}


2.指数操作符

指数运算符 ** , ** 具有与 Math.pow(..) 等效的计算结果。

Math.pow(2,10)   //1024

2**10 //1024

ES8新特性(2017)

1.async/await

async function process(array) {
for await (let i of array) {
doSomething(i);
}
}


2.Object.values()

Object.values() 是一个与 Object.keys() 类似的新函数,但返回的是Object自身属性的所有值,不包括继承的值

假设我们要遍历如下对象 obj的所有值:

const obj={a:1,b:2,c:3};


const keys=Object.keys(obj) //['a','b','c']

const values=Object.values(obj) // [1,2,3]


3.Object.entries()

Object.entries() 函数返回一个给定对象自身可枚举属性的键值对的数组。

const obj={a:1,b:2,c:3};

for (const [key, value] of Object.entries(obj)) {
console.log(`key:${key} value ${value}`)
}

// key:a value 1
// key:b value 2
// key:c value 3


4.String padding

String新增了两个实例函数 String.prototype.padStartString.prototype.padEnd,允许将空字符串或其他字符串添加到原始字符串的开头或结尾。

String.padStart(targetLength,[padString])
  • targetLength:当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身

  • padString:(可选)填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断,如果字符串太短,不足与填充,则会循环字符串以填充,此参数的缺省值为 “ “。

let a='0.0';
a.padStart(2,'10'); //'0.0'
a.padStart(10);    //'          0.0'
a.padStart(5,'10')   //'100.0'
a.padStart(5,'123') //'120.0'
a.padStart(6,'10') //'1010.0'
String.padEnd(targetLength,padString])
  • targetLength:当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身

  • padString:(可选) 填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断,如果字符串太短,不足与填充,则会循环字符串以填充,此参数的缺省值为 “ “;

let a='0.0';
a.padEnd(2,'10'); //'0.0'
a.padEnd(10);    //'0.0          '
a.padEnd(5,'10')   //'0.010'
a.padEnd(5,'123') //'0.012'
a.padEnd(6,'10') //'0.0101'


5.Object.getOwnPropertyDescriptors()

Object.getOwnPropertyDescriptors() 函数用来获取一个对象的所有自身属性的描述符,如果没有任何自身属性,则返回空对象

const obj2 = {
name: 'Jack',
get age() { return '20'}
}

Object.getOwnPropertyDescriptors(obj2)

// age: {
// configurable:true,
// enumerable:true,
// get:f age()..
// set:undefined,
// }
// name:{
// configurable:true,
// enumerable:true,
// value:'Jack',
// writable:true,
//}
  • value:与属性关联的值(仅限数据描述符)
  • writable:true 当且仅当与属性关联的值可能被更改时(仅限数据描述符)。
  • get:一个函数,用作属性的getter,或者undefined如果没有getter(仅限访问者描述符)。
  • set:一个函数,用作属性的setter,或者undefined如果没有setter(仅限访问者描述符)。
  • configurable:true 当且仅当可以更改此属性描述符的类型并且可以从相应对象中删除该属性时。
  • enumerable:true 当且仅当在枚举相应对象的属性期间显示此属性时。


6.SharedArrayBuffer对象

SharedArrayBuffer 对象用来表示一个通用的,固定长度的原始二进制数据缓冲区,类似于 ArrayBuffer 对象,它们都可以用来在共享内存(shared memory)上创建视图。与 ArrayBuffer 不同的是,SharedArrayBuffer 不能被分离

new ShareArrayBuffer(length)


7.Atomics对象

Atomics 对象提供了一组静态方法用来对 SharedArrayBuffer 对象进行原子操作。


ES9新特性(2018)

1.Promise.finally()

.finally() 允许你指定最终的逻辑:

function doSomething() {
doSomething1(4)
.then(() => {
return doSomething2(2);
})
.catch(err => {
console.log(err);
})
.finally(() => {
console.log('finally')
});
}


2.Rest/Spread 属性

提供了和Rest一样的参数

const Obj={
a:1,
b:2,
c:3
}

const {a,...x} = Obj;


ES10新特性(2019)

1. 行分隔符(U + 2028)和段分隔符(U + 2029)符号现在允许在字符串文字中,与JSON匹配


2.数组新增flat()flatMap()方法

flat()

[1, 2, [3, 4]].flat(Infinity); // [1, 2, 3, 4]

flatMap()

[1, 2, 3, 4].flatMap(a => [a**2]); // [1, 4, 9, 16]


3.Symbol.prototype.description

只读属性,回 Symbol 对象的可选描述的字符串。

Symbol('description').description; // 'description'


4. Object.fromEntries()

返回一个给定对象自身可枚举属性的键值对数组

// 通过 Object.fromEntries, 可以将 Map 转化为 Object:
const map = new Map([ ['foo', 'bar'], ['baz', 42] ]);
console.log(Object.fromEntries(map)); // { foo: "bar", baz: 42 }



ES11新特性(2020)

1. Nullish coalescing Operator(空值处理)

表达式在 ?? 的左侧 运算符求值为undefined或null,返回其右侧。

let user = {
u1: 0,
u2: false,
u3: null,
u4: undefined
u5: '',
}
let u2 = user.u2 ?? '用户2' // false
let u3 = user.u3 ?? '用户3' // 用户3
let u4 = user.u4 ?? '用户4' // 用户4
let u5 = user.u5 ?? '用户5' // ''


2. Optional chaining(可选链)

?.用户检测不确定的中间节点

let user = {}
let u1 = user.childer.name // TypeError: Cannot read property 'name' of undefined
let u1 = user.childer?.name // undefined