
ES6系列目录
- 1 let 和 const命令
- 2 变量的解构赋值
- 3 字符串的拓展
- 4 正则的拓展
- 5 数值的拓展
- 6 函数的拓展
- 7 数组的拓展
- 8 对象的拓展
- 9 Symbol
- 10 Set和Map数据结构
- 11 Proxy
- 12 Promise对象
- 13 Iterator和 for...of循环
- 14 Generator函数和应用
- 15 Class语法和继承
- 16 Module语法和加载实现
所有整理的文章都收录到我《Cute-JavaScript》系列文章中,访问地址:http://js.pingan8787.com
5 数值的拓展
5.1 Number.isFinite(), Number.isNaN()
Number.isFinite() 用于检查一个数值是否是有限的,即不是 Infinity,若参数不是 Number类型,则一律返回 false 。
-
Number.isFinite(10); // true -
Number.isFinite(0.5); // true -
Number.isFinite(NaN); // false -
Number.isFinite(Infinity); // false -
Number.isFinite(-Infinity); // false -
Number.isFinite('leo'); // false -
Number.isFinite('15'); // false -
Number.isFinite(true); // false -
Number.isFinite(Math.random()); // true
Number.isNaN()用于检查是否是 NaN,若参数不是 NaN,则一律返回 false。
-
Number.isNaN(NaN); // true -
Number.isNaN(10); // false -
Number.isNaN('10'); // false -
Number.isNaN(true); // false -
Number.isNaN(5/NaN); // true -
Number.isNaN('true' / 0); // true -
Number.isNaN('true' / 'true'); // true
区别:
与传统全局的 isFinite()和 isNaN()方法的区别,传统的这两个方法,是先将参数转换成数值,再判断。
而ES6新增的这两个方法则只对数值有效, Number.isFinite()对于非数值一律返回 false, Number.isNaN()只有对于 NaN才返回 true,其他一律返回 false。
-
isFinite(25); // true -
isFinite("25"); // true -
Number.isFinite(25); // true -
Number.isFinite("25"); // false -
isNaN(NaN); // true -
isNaN("NaN"); // true -
Number.isNaN(NaN); // true -
Number.isNaN("NaN"); // false
5.2 Number.parseInt(), Number.parseFloat()
这两个方法与全局方法 parseInt()和 parseFloat()一致,目的是逐步减少全局性的方法,让语言更模块化。
-
parseInt('12.34'); // 12 -
parseFloat('123.45#'); // 123.45 -
Number.parseInt('12.34'); // 12 -
Number.parseFloat('123.45#'); // 123.45 -
Number.parseInt === parseInt; // true -
Number.parseFloat === parseFloat; // true
5.3 Number.isInteger()
用来判断一个数值是否是整数,若参数不是数值,则返回 false。
-
Number.isInteger(10); // true -
Number.isInteger(10.0); // true -
Number.isInteger(10.1); // false
5.4 Math对象的拓展
ES6新增17个数学相关的静态方法,只能在Math对象上调用。
- Math.trunc:
用来去除小数的小数部分,返回整数部分。
若参数为非数值,则先转为数值。
若参数为空值或无法截取整数的值,则返回NaN。
-
// 正常使用 -
Math.trunc(1.1); // 1 -
Math.trunc(1.9); // 1 -
Math.trunc(-1.1); // -1 -
Math.trunc(-1.9); // -1 -
Math.trunc(-0.1234); // -0 -
// 参数为非数值 -
Math.trunc('11.22'); // 11 -
Math.trunc(true); // 1 -
Math.trunc(false); // 0 -
Math.trunc(null); // 0 -
// 参数为空和无法取整 -
Math.trunc(NaN); // NaN -
Math.trunc('leo'); // NaN -
Math.trunc(); // NaN -
Math.trunc(undefined); // NaN
ES5实现:
-
Math.trunc = Math.trunc || function(x){ -
return x < 0 ? Math.ceil(x) : Math.floor(x); -
}
- Math.sign():
判断一个数是正数、负数还是零,对于非数值,会先转成数值。
返回值:
- 参数为正数, 返回 +1
- 参数为负数, 返回 -1
- 参数为0, 返回 0
- 参数为-0, 返回 -0
- 参数为其他值, 返回 NaN
-
Math.sign(-1); // -1 -
Math.sign(1); // +1 -
Math.sign(0); // 0 -
Math.sign(-0); // -0 -
Math.sign(NaN); // NaN -
Math.sign(''); // 0 -
Math.sign(true); // +1 -
Math.sign(false);// 0 -
Math.sign(null); // 0 -
Math.sign('9'); // +1 -
Math.sign('leo');// NaN -
Math.sign(); // NaN -
Math.sign(undefined); // NaN
ES5实现
-
Math.sign = Math.sign || function (x){ -
x = +x; -
if (x === 0 || isNaN(x)){ -
return x; -
} -
return x > 0 ? 1: -1; -
}
- Math.cbrt():
用来计算一个数的立方根,若参数为非数值则先转成数值。
-
Math.cbrt(-1); // -1 -
Math.cbrt(0); // 0 -
Math.cbrt(1); // 1 -
Math.cbrt(2); // 1.2599210498 -
Math.cbrt('1'); // 1 -
Math.cbrt('leo'); // NaN
ES5实现
-
Math.cbrt = Math.cbrt || function (x){ -
var a = Math.pow(Math.abs(x), 1/3); -
return x < 0 ? -y : y; -
}
- Math.clz32():
用于返回一个数的 32 位无符号整数形式有多少个前导 0。
-
Math.clz32(0) // 32 -
Math.clz32(1) // 31 -
Math.clz32(1000) // 22 -
Math.clz32(0b01000000000000000000000000000000) // 1 -
Math.clz32(0b00100000000000000000000000000000) // 2
- Math.imul():
用于返回两个数以 32 位带符号整数形式相乘的结果,返回的也是一个 32 位的带符号整数。
-
Math.imul(2, 4) // 8 -
Math.imul(-1, 8) // -8 -
Math.imul(-2, -2) // 4
- Math.fround():
用来返回一个数的2位单精度浮点数形式。
-
Math.fround(0) // 0 -
Math.fround(1) // 1 -
Math.fround(2 ** 24 - 1) // 16777215
- Math.hypot():
用来返回所有参数的平方和的平方根。
-
Math.hypot(3, 4); // 5 -
Math.hypot(3, 4, 5); // 7.0710678118654755 -
Math.hypot(); // 0 -
Math.hypot(NaN); // NaN -
Math.hypot(3, 4, 'foo'); // NaN -
Math.hypot(3, 4, '5'); // 7.0710678118654755 -
Math.hypot(-3); // 3
- Math.expm1():
用来返回 ex-1,即 Math.exp(x)-1。
-
Math.expm1(-1) // -0.6321205588285577 -
Math.expm1(0) // 0 -
Math.expm1(1) // 1.718281828459045
ES5实现
-
Math.expm1 = Math.expm1 || function(x) { -
return Math.exp(x) - 1; -
};
- Math.log1p():
用来返回 1+x的自然对数,即 Math.log(1+x)。如果x小于 -1,返回 NaN。
-
Math.log1p(1) // 0.6931471805599453 -
Math.log1p(0) // 0 -
Math.log1p(-1) // -Infinity -
Math.log1p(-2) // NaN
ES5实现
-
Math.log1p = Math.log1p || function(x) { -
return Math.log(1 + x); -
};
- Math.log10():
用来返回以 10为底的 x的对数。如果x小于 0,则返回 NaN。
-
Math.log10(2) // 0.3010299956639812 -
Math.log10(1) // 0 -
Math.log10(0) // -Infinity -
Math.log10(-2) // NaN -
Math.log10(100000) // 5
ES5实现
-
Math.log10 = Math.log10 || function(x) { -
return Math.log(x) / Math.LN10; -
};
- Math.log2():
用来返回以 2 为底的 x的对数。如果 x小于 0,则返回 NaN。
-
Math.log2(3) // 1.584962500721156 -
Math.log2(2) // 1 -
Math.log2(1) // 0 -
Math.log2(0) // -Infinity -
Math.log2(-2) // NaN -
Math.log2(1024) // 10 -
Math.log2(1 << 29) // 29
ES5实现
-
Math.log2 = Math.log2 || function(x) { -
return Math.log(x) / Math.LN2; -
};
- 双曲函数方法:
-
Math.sinh(x) 返回x的双曲正弦(hyperbolic sine) -
Math.cosh(x) 返回x的双曲余弦(hyperbolic cosine) -
Math.tanh(x) 返回x的双曲正切(hyperbolic tangent) -
Math.asinh(x) 返回x的反双曲正弦(inverse hyperbolic sine) -
Math.acosh(x) 返回x的反双曲余弦(inverse hyperbolic cosine) -
Math.atanh(x) 返回x的反双曲正切(inverse hyperbolic tangent)
5.5 指数运算符
新增的指数运算符( **):
-
2 ** 2; // 4 -
2 ** 3; // 8 -
2 ** 3 ** 2; // 相当于 2 ** (3 ** 2); 返回 512
指数运算符( **)与 Math.pow的实现不相同,对于特别大的运算结果,两者会有细微的差异。
-
Math.pow(99, 99) -
// 3.697296376497263e+197 -
99 ** 99 -
// 3.697296376497268e+197
6 函数的拓展
6.1 参数默认值
-
// ES6 之前 -
function f(a, b){ -
b = b || 'leo'; -
console.log(a, b); -
} -
// ES6 之后 -
function f(a, b='leo'){ -
console.log(a, b); -
} -
f('hi'); // hi leo -
f('hi', 'jack'); // hi jack -
f('hi', ''); // hi leo
注意:
- 参数变量是默认声明的,不能用
let和 const再次声明:
-
function f (a = 1){ -
let a = 2; // error -
}
- 使用参数默认值时,参数名不能相同:
-
function f (a, a, b){ ... }; // 不报错 -
function f (a, a, b = 1){ ... }; // 报错
与解构赋值默认值结合使用:
-
function f ({a, b=1}){ -
console.log(a,b) -
}; -
f({}); // undefined 1 -
f({a:2}); // 2 1 -
f({a:2, b:3}); // 2 3 -
f(); // 报错 -
function f ({a, b = 1} = {}){ -
console.log(a, b) -
} -
f(); // undefined 1
尾参数定义默认值:
通常在尾参数定义默认值,便于观察参数,并且非尾参数无法省略。
-
function f (a=1,b){ -
return [a, b]; -
} -
f(); // [1, undefined] -
f(2); // [2, undefined] -
f(,2); // 报错 -
f(undefined, 2); // [1, 2] -
function f (a, b=1, c){ -
return [a, b, c]; -
} -
f(); // [undefined, 1, undefined] -
f(1); // [1,1,undefined] -
f(1, ,2); // 报错 -
f(1,undefined,2); // [1,1,2]
在给参数传递默认值时,传入 undefined会触发默认值,传入 null不会触发。
-
function f (a = 1, b = 2){ -
console.log(a, b); -
} -
f(undefined, null); // 1 null
函数的length属性:
length属性将返回,没有指定默认值的参数数量,并且rest参数不计入 length属性。
-
function f1 (a){...}; -
function f2 (a=1){...}; -
function f3 (a, b=2){...}; -
function f4 (...a){...}; -
function f5 (a,b,...c){...}; -
f1.length; // 1 -
f2.length; // 0 -
f3.length; // 1 -
f4.length; // 0 -
f5.length; // 2
6.2 rest 参数
rest参数形式为( ...变量名),其值为一个数组,用于获取函数多余参数。
-
function f (a, ...b){ -
console.log(a, b); -
} -
f(1,2,3,4); // 1 [2, 3, 4]
注意:
-
rest参数只能放在最后一个,否则报错:
-
function f(a, ...b, c){...}; // 报错
- 函数的
length属性不包含 rest参数。
-
function f1 (a){...}; -
function f2 (a,...b){...}; -
f1(1); // 1 -
f2(1,2); // 1
6.3 name 属性
用于返回该函数的函数名。
-
function f (){...}; -
f.name; // f -
const f = function g(){...}; -
f.name; // g
6.4 箭头函数
使用“箭头”( =>)定义函数。
基础使用:
-
// 有1个参数 -
let f = v => v; -
// 等同于 -
let f = function (v){return v}; -
// 有多个参数 -
let f = (v, i) => {return v + i}; -
// 等同于 -
let f = function (v, i){return v + i}; -
// 没参数 -
let f = () => 1; -
// 等同于 -
let f = function (){return 1};
箭头函数与变量结构结合使用:
-
// 正常函数写法 -
function f (p) { -
return p.a + ':' + p.b; -
} -
// 箭头函数写法 -
let f = ({a, b}) => a + ':' + b;
简化回调函数:
-
// 正常函数写法 -
[1, 2, 3].map(function (x){ -
return x * x; -
}) -
// 箭头函数写法 -
[1, 2, 3].map(x => x * x);
箭头函数与rest参数结合:
-
let f = (...n) => n; -
f(1, 2, 3); // [1, 2, 3]
注意点:
- 1.箭头函数内的
this总是指向定义时所在的对象,而不是调用时。 - 2.箭头函数不能当做构造函数,即不能用
new命令,否则报错。 - 3.箭头函数不存在
arguments对象,即不能使用,可以使用 rest参数代替。 - 4.箭头函数不能使用
yield命令,即不能用作Generator函数。
不适用场景:
- 1.在定义函数方法,且该方法内部包含
this。
-
const obj = { -
a:9, -
b: () => { -
this.a --; -
} -
}
上述 b如果是普通函数,函数内部的 this指向 obj,但是如果是箭头函数,则 this会指向全局,不是预期结果。
- 2.需要动态
this时。
-
let b = document.getElementById('myID'); -
b.addEventListener('click', ()=>{ -
this.classList.toggle('on'); -
})
上诉按钮点击会报错,因为 b监听的箭头函数中, this是全局对象,若改成普通函数, this就会指向被点击的按钮对象。
6.5 双冒号运算符
双冒号暂时是一个提案,用于解决一些不适用的场合,取代 call、 apply、 bind调用。
双冒号运算符( ::)的左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即 this对象),绑定到右边函数上。
-
f::b; -
// 等同于 -
b.bind(f); -
f::b(...arguments); -
// 等同于 -
b.apply(f, arguments);
若双冒号左边为空,右边是一个对象的方法,则等于将该方法绑定到该对象上。
-
let f = a::a.b; -
// 等同于 -
let f = ::a.b;
7 数组的拓展
7.1 拓展运算符
拓展运算符使用( ...),类似 rest参数的逆运算,将数组转为用( ,)分隔的参数序列。
-
console.log(...[1, 2, 3]); // 1 2 3 -
console.log(1, ...[2,3], 4); // 1 2 3 4
拓展运算符主要使用在函数调用。
-
function f (a, b){ -
console.log(a, b); -
} -
f(...[1, 2]); // 1 2 -
function g (a, b, c, d, e){ -
console.log(a, b, c, d, e); -
} -
g(0, ...[1, 2], 3, ...[4]); // 0 1 2 3 4
若拓展运算符后面是个空数组,则不产生效果。
-
[...[], 1]; // [1]
替代apply方法
-
// ES6之前 -
function f(a, b, c){...}; -
var a = [1, 2, 3]; -
f.apply(null, a); -
// ES6之后 -
function f(a, b, c){...}; -
let a = [1, 2, 3]; -
f(...a); -
// ES6之前 -
Math.max.apply(null, [3,2,6]); -
// ES6之后 -
Math.max(...[3,2,6]);
拓展运算符的运用
- (1)复制数组:
通常我们直接复制数组时,只是浅拷贝,如果要实现深拷贝,可以使用拓展运算符。
-
// 通常情况 浅拷贝 -
let a1 = [1, 2]; -
let a2 = a1; -
a2[0] = 3; -
console.log(a1,a2); // [3,2] [3,2] -
// 拓展运算符 深拷贝 -
let a1 = [1, 2]; -
let a2 = [...a1]; -
// let [...a2] = a1; // 作用相同 -
a2[0] = 3; -
console.log(a1,a2); // [1,2] [3,2]
- (2)合并数组:
注意,这里合并数组,只是浅拷贝。
-
let a1 = [1,2]; -
let a2 = [3]; -
let a3 = [4,5]; -
// ES5 -
let a4 = a1.concat(a2, a3); -
// ES6 -
let a5 = [...a1, ...a2, ...a3]; -
a4[0] === a1[0]; // true -
a5[0] === a1[0]; // true
- (3)与解构赋值结合:
与解构赋值结合生成数组,但是使用拓展运算符需要放到参数最后一个,否则报错。
-
let [a, ...b] = [1, 2, 3, 4]; -
// a => 1 b => [2,3,4] -
let [a, ...b] = []; -
// a => undefined b => [] -
let [a, ...b] = ["abc"]; -
// a => "abc" b => []
7.2 Array.from()
将 类数组对象 和 可遍历的对象,转换成真正的数组。
-
// 类数组对象 -
let a = { -
'0':'a', -
'1':'b', -
length:2 -
} -
let arr = Array.from(a); -
// 可遍历的对象 -
let a = Array.from([1,2,3]); -
let b = Array.from({length: 3}); -
let c = Array.from([1,2,3]).map(x => x * x); -
let d = Array.from([1,2,3].map(x => x * x));
7.3 Array.of()
将一组数值,转换成数组,弥补 Array方法参数不同导致的差异。
-
Array.of(1,2,3); // [1,2,3] -
Array.of(1).length; // 1 -
Array(); // [] -
Array(2); // [,] 1个参数时,为指定数组长度 -
Array(1,2,3); // [1,2,3] 多于2个参数,组成新数组
7.4 find()和findIndex()
find()方法用于找出第一个符合条件的数组成员,参数为一个回调函数,所有成员依次执行该回调函数,返回第一个返回值为 true的成员,如果没有一个符合则返回 undefined。
-
[1,2,3,4,5].find( a => a < 3 ); // 1
回调函数接收三个参数,当前值、当前位置和原数组。
-
[1,2,3,4,5].find((value, index, arr) => { -
// ... -
});
findIndex()方法与 find()类似,返回第一个符合条件的数组成员的位置,如果都不符合则返回 -1。
-
[1,2,3,4].findIndex((v,i,a)=>{ -
return v>2; -
}); // 2
7.5 fill()
用于用指定值填充一个数组,通常用来初始化空数组,并抹去数组中已有的元素。
-
new Array(3).fill('a'); // ['a','a','a'] -
[1,2,3].fill('a'); // ['a','a','a']
并且 fill()的第二个和第三个参数指定填充的起始位置和结束位置。
-
[1,2,3].fill('a',1,2);// [1, "a", 3]
7.6 entries(),keys(),values()
主要用于遍历数组, entries()对键值对遍历, keys()对键名遍历, values()对键值遍历。
-
for (let i of ['a', 'b'].keys()){ -
console.log(i) -
} -
// 0 -
// 1 -
for (let e of ['a', 'b'].values()){ -
console.log(e) -
} -
// 'a' -
// 'b' -
for (let e of ['a', 'b'].entries()){ -
console.log(e) -
} -
// 0 'a' -
// 1 'b'
7.7 includes()
用于表示数组是否包含给定的值,与字符串的 includes方法类似。
-
[1,2,3].includes(2); // true -
[1,2,3].includes(4); // false -
[1,2,NaN].includes(NaN); // true
第二个参数为起始位置,默认为 0,如果负数,则表示倒数的位置,如果大于数组长度,则重置为 0开始。
-
[1,2,3].includes(3,3); // false -
[1,2,3].includes(3,4); // false -
[1,2,3].includes(3,-1); // true -
[1,2,3].includes(3,-4); // true
7.8 flat(),flatMap()
flat()用于将数组一维化,返回一个新数组,不影响原数组。
默认一次只一维化一层数组,若需多层,则传入一个整数参数指定层数。
若要一维化所有层的数组,则传入 Infinity作为参数。
-
[1, 2, [2,3]].flat(); // [1,2,2,3] -
[1,2,[3,[4,[5,6]]]].flat(3); // [1,2,3,4,5,6] -
[1,2,[3,[4,[5,6]]]].flat('Infinity'); // [1,2,3,4,5,6]
flatMap()是将原数组每个对象先执行一个函数,在对返回值组成的数组执行 flat()方法,返回一个新数组,不改变原数组。
flatMap()只能展开一层。
-
[2, 3, 4].flatMap((x) => [x, x * 2]); -
// [2, 4, 3, 6, 4, 8]

