1.数值的扩展
(1)Number.EPSILON:ES6 在 Number 对象上,新增一个极小的常量,表示 1 与 大于 1 的最小浮点数之差。
(2)Math.trunc():去除一个数的小数部分,返回整数部分。
(3)Math.sign():用来判断一个数是整数、负数还是零。
(4)Math.hypot():返回所有参数的平方和的平方根
(5)Math.cbrt():用于计算一个数的立方根。
(6)Math.clz32():将参数转为 32 位无符号整数的形式,然后返回这个 32 位值里面有多少个前导 0 。
Math.clz32(0); //32 0的二进制形式全为0,故前导有32个0
Math.clz32(1); //31 1的二进制形式为 0b1,只占1位,故32位之中有31个前导0
Math.clz32(0b01000000000000000000000000000000); //1
(7)Math.imul():返回两个数以32位带符号整数形式相乘的结果,返回的也是一个32位带符号整数。
(8)Math.fround():返回一个数的32位单精度浮点数形式。
(9)新增四个对数相关方法
Math.expm1(x):返回 e^x-1即 Math.exp(x)-1
Math.log1p(x):返回 1+x 的自然对数,即 Math.log(1+x),如果 x 小于 -1,则返回 NaN
Math.log10(x):返回以 10 为底的 x 的对数,如果 x 小于 0,则返回 NaN
Math.log2(x):返回以 2 为底的 x 的对数,如果 x 小于 -1,则返回 NaN
(10)** :指数运算符,特点是右结合,而不是左结合
2 ** 2 //4
2 ** 3 //8
let b = 4
b **= 3 // b = b*b*b
(11)BigInt 数据类型:BigInt 类型的数据必须添加后缀 n
(12)BigInt 对象 你不给一个
BigInt() 构造函数必须有参数,而且参数必须可以正常转为数值。参数若是小数也会报错。
2.函数的扩展
(1)函数的 length 属性,返回没有指定默认值的参数个数(为默认值前面的参数的个数)。不包括 rest 参数。
(2)rest 参数(...变量名):用于获取函数的多余参数,这样就不用 arguments 对象了。这个参数搭配的是一个数组,该变量将多余的参数放入数组中。在 rest 参数后面不能再有其它参数
function add(...values){
let sum = 0;
for (let val of values){
sum += val;
}
return sum;
}
add(2,5,3); //10
rest 参数代替 arguments 的例子
//arguments 写法
function sortNumber(){
return Array.prototype.slice.call(arguments).sort();
}
//rest 参数写法
const sortNumbers = (...numbers) => numbers.sort();
(3)ES6 规定,只要函数参数使用了默认值,解构赋值或者扩展运算符,那么函数内部就不能显示设定为严格模式。原因是函数体内的严格模式适用于函数体和函数参数,而函数执行的时候限制性参数再执行函数体。两种方法可以规避这种限制
一、设定全局性的严格模式
'use strict';
function doSomething(a,b = a){
...
}
二、把函数包在一个无参数的立即执行函数里面
const doSomething = (function(){
'use strict'
return function(value = 42){
return value;
}
}());
(4)name 属性:返回函数的名字。
构造函数返回的函数实例,name 属性的值为 anonymous
(new Function).name; //anonymous
bind 返回的函数,name 属性值前面会加上 bound 前缀
function foo(){};
foo.bind({}).name; //"bound foo"
(function(){}).bind({}).name;//"bound"
(5)箭头函数:使用 => 定义函数
var f = v => v;
//等同于
var f = function(v){
return v;
};
若箭头函数不需要参数或需要多个参数,就使用圆括号代表参数部分。
//例1
var f = () => 5;
//等同于
var f = function(){
return 5;
}
//例2
var sum = (num1,num2) => num1 + num2;
//等同于
var sum = function(num1,num2){
return num1 + num2;
};
若箭头函数的代码块多于一条语句,就用花括号包起来,并用 return 语句返回。
var sum = (num1,num2) => {return num1 + num2};
由于花括号被解释为代码块,若箭头函数返回一个对象,则必须在花括号外面再包上圆括号,否则会报错。
let getTempItem = id => {id : id,name : "temp"}; //报错
let getTempItem = id =>({id : id,name : "temp"}); //不报错
遇到特殊情况会运行,但结果错误。
let foo = {} => {a:1};
foo(); //undefined
/* 因为花括号为代码块,所以执行了一行语句 a:1,这时 a 被解释为语句的标签,因此,实际执行的语句是 1; 然后函数就结束了,没有返回值
*/
若箭头函数只有一行语句,且不需要返回值,就不用花括号了
let fn = () => void doesNotReturn();
箭头函数可以与变量结合使用
const full = ({first,last}) => first + " " + last;
//等同于
function full(person){
return person.first + "" + person.last;
}
箭头函数的用处:
一:简化回调函数
//正常函数写法
[1,2,3].map(function(x){
return x * x;
});
//箭头函数写法
[1,2,3].map(x => x * x);
二:rest 参数与箭头函数结合的例子
//例1
const numbers = (...num) => num;
numbers(1,2,3,4,5); //[1,2,3,4,5]
//例2
const headAndTail = (head,...tail) => [head,tail];
headAndTail(1,2,3,4,5); //[1,[2,3,4,5]]
使用箭头函数时需注意!
一:函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。
二:不可以当做构造函数,也就是说不可以使用 new 命令,否则会抛出一个错误。
三:不可以使用 arguments 对象,该对象在函数体内不存在,若要使用,则用 rest 代替。
四:不可使用 yeild 命令,因为箭头函数不能用作 Generator 函数。
不适用箭头函数的场合
一、定义对象的方法,且该方法内部包括 this。
const cat = {
lives:9,
jumps:() => {
return this.lives--;
}
};
/*此时 this 指向全局变量,得不到预期的结果。这是因为对象不构成单独的作用域,使得 jumps 箭头函数定义时的作用域就是全局作用域。
*/
二、需要动态 this 时,也不应使用箭头函数
var button = document.getElementById("press");
button.addEventListener("click",() => {
this.classList.toggle("on");
});
/*
点击按钮会报错,因为 button 的监听函数是箭头函数,导致里面的 this 就是全局对象
*/
(6)尾调用:某个函数的最后一步是调用另一个函数
(7)尾递归:函数调用自身成为递归,在最后一步调用自身成为尾递归。
递归非常耗费内存,因为要同时调用成千上百个调用帧,很容易发生“栈溢出”(stack overflow)错误。但对于尾递归来说,只存在一个调用帧,永远不会发生栈溢出错误。