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;
网友评论