边黎an带你走进es678

1.1 let 和 const命令

在ES6中,我们通常实用 let 表示变量const 表示常量,并且 let 和 const 都是块级作用域,且在当前作用域有效不能重复声明。

1.1.1 let 命令

let 命令的用法和 var 相似,但是 let 只在所在代码块内有效。
基础用法

 
  1. {

  2. let a = 1;

  3. let b = 2;

  4. }

  5. 复制代码

并且 let 有以下特点:

  • 不存在变量提升:
    在ES6之前,我们 var 声明一个变量一个函数,都会伴随着变量提升的问题,导致实际开发过程经常出现一些逻辑上的疑惑,按照一般思维习惯,变量都是需要先声明后使用。
 
  1. // var

  2. console.log(v1); // undefined

  3. var v1 = 2;

  4. // 由于变量提升 代码实际如下

  5. var v1;

  6. console.log(v1)

  7. v1 = 2;

  8.  
  9. // let

  10. console.log(v2); // ReferenceError

  11. let v2 = 2;

  12. 复制代码

  • 不允许重复声明:
    let 和 const 在相同作用域下,都不能重复声明同一变量,并且不能在函数内重新声明参数
 
  1. // 1. 不能重复声明同一变量

  2. // 报错

  3. function f1 (){

  4. let a = 1;

  5. var a = 2;

  6. }

  7. // 报错

  8. function f2 (){

  9. let a = 1;

  10. let a = 2;

  11. }

  12.  
  13. // 2. 不能在函数内重新声明参数

  14. // 报错

  15. function f3 (a1){

  16. let a1;

  17. }

  18. // 不报错

  19. function f4 (a2){

  20. {

  21. let a2

  22. }

  23. }

  24. 复制代码

1.1.2 const 命令

const 声明一个只读常量
基础用法

 
  1. const PI = 3.1415926;

  2. console.log(PI); // 3.1415926

  3.  
  4. 复制代码

注意点

  • const 声明后,无法修改值;
 
  1. const PI = 3.1415926;

  2. PI = 3;

  3. // TypeError: Assignment to constant variable.

  4. 复制代码

  • const 声明时,必须赋值;
 
  1. const a ;

  2. // SyntaxError: Missing initializer in const declaration.

  3. 复制代码

  • const 声明的常量,let 不能重复声明;
 
  1. const PI = 3.1415926;

  2. let PI = 0;

  3. // Uncaught SyntaxError: Identifier 'PI' has already been declared

  4. 复制代码

1.2 变量的解构赋值

解构赋值概念:在ES6中,直接从数组和对象中取值,按照对应位置,赋值给变量的操作。

1.2.1 数组

基础用法

 
  1. // ES6 之前

  2. let a = 1;

  3. let b = 2;

  4.  
  5. // ES6 之后

  6. let [a, b] = [1, 2];

  7. 复制代码

本质上,只要等号两边模式一致,左边变量即可获取右边对应位置的值,更多用法:

 
  1. let [a, [[b], c]] = [1, [[2], 3]];

  2. console.log(a, b, c); // 1, 2, 3

  3.  
  4. let [ , , c] = [1, 2, 3];

  5. console.log(c); // 3

  6.  
  7. let [a, , c] = [1, 2, 3];

  8. console.log(a,c); // 1, 3

  9.  
  10. let [a, ...b] = [1, 2, 3];

  11. console.log(a,b); // 1, [2,3]

  12.  
  13. let [a, b, ..c.] = [1];

  14. console.log(a, b, c); // 1, undefined, []

  15. 复制代码

注意点

  • 如果解构不成功,变量的值就等于undefined
 
  1. let [a] = []; // a => undefined

  2. let [a, b] = [1]; // a => 1 , b => undefined

  3. 复制代码

  • 当左边模式多于右边,也可以解构成功。
 
  1. let [a, b] = [1, 2, 3];

  2. console.log(a, b); // 1, 2

  3. 复制代码

  • 两边模式不同,报错。
 
  1. let [a] = 1;

  2. let [a] = false;

  3. let [a] = NaN;

  4. let [a] = undefined;

  5. let [a] = null;

  6. let [a] = {};

  7. 复制代码

指定解构的默认值
基础用法

 
  1. let [a = 1] = []; // a => 1

  2. let [a, b = 2] = [a]; // a => 1 , b => 2

  3. 复制代码

特殊情况:

 
  1. let [a = 1] = [undefined]; // a => 1

  2. let [a = 1] = [null]; // a => null

  3. 复制代码

右边模式对应的值,必须严格等于undefined,默认值才能生效,而null不严格等于undefined

1.2.2 对象的解构赋值

与数组解构不同的是,对象解构不需要严格按照顺序取值,而只要按照变量名去取对应属性名的值,若取不到对应属性名的值,则为undefined 。

基础用法

 
  1. let {a, b} = {a:1, b:2}; // a => 1 , b => 2

  2. let {a, b} = {a:2, b:1}; // a => 2 , b => 1

  3. let {a} = {a:3, b:2, c:1};// a => 3

  4. let {a} = {b:2, c:1}; // a => undefined

  5. 复制代码

注意点

  • 变量名属性名不一致,则需要修改名称。
 
  1. let {a:b} = {a:1, c:2};

  2. // error: a is not defined

  3. // b => 1

  4. 复制代码

对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
上面代码中,a 是匹配的模式,b才是变量。真正被赋值的是变量b,而不是模式a

  • 对象解构也支持嵌套解构
 
  1. let obj = {

  2. a:[ 1, { b: 2}]

  3. };

  4. let {a, a: [c, {b}]} = obj;

  5. // a=>[1, {b: 2}], b => 2, c => 1

  6. 复制代码

指定解构的默认值

 
  1. let {a=1} = {}; // a => 1

  2. let {a, b=1} = {a:2}; // a => 2, b => 1

  3.  
  4. let {a:b=3} = {}; // b => 3

  5. let {a:b=3} = {a:4}; // b = >4

  6. // a是模式,b是变量 牢记

  7.  
  8. let {a=1} = {a:undefined}; // a => 1

  9. let {a=1} = {a:null}; // a => null

  10. // 因为null与undefined不严格相等,所以赋值有效

  11. // 导致默认值1不会生效。

  12. 复制代码

1.2.3 字符串的解构赋值

字符串的解构赋值中,字符串被转换成了一个类似数组的对象。 基础用法

 
  1. const [a, b, c, d, e] = 'hello';

  2. a // "h"

  3. b // "e"

  4. c // "l"

  5. d // "l"

  6. e // "o"

  7.  
  8. let {length:len} = 'hello';// len => 5

  9. 复制代码

1.2.4 数值和布尔值的解构赋值

解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefinednull无法转为对象,所以对它们进行解构赋值,都会报错。

 
  1. // 数值和布尔值的包装对象都有toString属性

  2. let {toString: s} = 123;

  3. s === Number.prototype.toString // true

  4. let {toString: s} = true;

  5. s === Boolean.prototype.toString // true

  6.  
  7. let { prop: x } = undefined; // TypeError

  8. let { prop: y } = null; // TypeError

  9. 复制代码

1.2.5 函数参数的解构赋值

基础用法

 
  1. function fun ([a, b]){

  2. return a + b;

  3. }

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

  5. 复制代码

指定默认值的解构:

 
  1. function fun ({a=0, b=0} = {}){

  2. return [a, b];

  3. }

  4. fun ({a:1, b:2}); // [1, 2]

  5. fun ({a:1}); // [1, 0]

  6. fun ({}); // [0, 0]

  7. fun (); // [0, 0]

  8.  
  9. function fun ({a, b} = {a:0, b:0}){

  10. return [a, b];

  11. }

  12. fun ({a:1, b:2}); // [1, 2]

  13. fun ({a:1}); // [1, undefined]

  14. fun ({}); // [undefined, undefined]

  15. fun (); // [0, 0]

  16. 复制代码

1.2.6 应用

  • 交换变量的值:
 
  1. let a = 1,b = 2;

  2. [a, b] = [b, a]; // a =>2 , b => 1

  3. 复制代码

  • 函数返回多个值:
 
  1. // 返回一个数组

  2. function f (){

  3. return [1, 2, 3];

  4. }

  5. let [a, b, c] = f(); // a=>1, b=>2, c=>3

  6.  
  7. // 返回一个对象

  8. function f (){

  9. return {a:1, b:2};

  10. }

  11. let {a, b} = f(); // a=>1, b=>2

  12. 复制代码

  • 快速对应参数: 快速的将一组参数与变量名对应。
 
  1. function f([a, b, c]) {...}

  2. f([1, 2, 3]);

  3.  
  4. function f({a, b, c}) {...}

  5. f({b:2, c:3, a:1});

  6. 复制代码

  • 提取JSON数据
 
  1. let json = {

  2. name : 'leo',

  3. age: 18

  4. }

  5. let {name, age} = json;

  6. console.log(name,age); // leo, 18

  7. 复制代码

  • 遍历Map结构:
 
  1. const m = new Map();

  2. m.set('a',1);

  3. m.set('b',2);

  4. for (let [k, v] of m){

  5. console.log(k + ' : ' + v);

  6. }

  7. // 获取键名

  8. for (let [k] of m){...}

  9. // 获取键值

  10. for (let [,k] of m){...}

  11. 复制代码

  • 输入模块的指定方法: 用于按需加载模块中需要用到的方法。
 
  1. const {log, sin, cos} = require('math');

  2. 复制代码

1.3 字符串的拓展

1.3.1 includes(),startsWith(),endsWith()

在我们判断字符串是否包含另一个字符串时,ES6之前,我们只有typeof方法,ES6之后我们又多了三种方法:

  • includes():返回布尔值,表示是否找到参数字符串
  • startsWith():返回布尔值,表示参数字符串是否在原字符串的头部
  • endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部
 
  1. let a = 'hello leo';

  2. a.startsWith('leo'); // false

  3. a.endsWith('o'); // true

  4. a.includes('lo'); // true

  5. 复制代码

并且这三个方法都支持第二个参数,表示起始搜索的位置。

 
  1. let a = 'hello leo';

  2. a.startsWith('leo',1); // false

  3. a.endsWith('o',5); // true

  4. a.includes('lo',6); // false

  5. 复制代码

endsWith 是针对前 n 个字符,而其他两个是针对从第n个位置直到结束。

1.3.2 repeat()

repeat方法返回一个新字符串,表示将原字符串重复n次。
基础用法

 
  1. 'ab'.repeat(3); // 'ababab'

  2. 'ab'.repeat(0); // ''

  3. 复制代码

特殊用法:

  • 参数为小数,则取整
 
  1. 'ab'.repeat(2.3); // 'abab'

  2. 复制代码

  • 参数为负数Infinity,则报错
 
  1. 'ab'.repeat(-1); // RangeError

  2. 'ab'.repeat(Infinity); // RangeError

  3. 复制代码

  • 参数为0到-1的小数NaN,则取0
 
  1. 'ab'.repeat(-0.5); // ''

  2. 'ab'.repeat(NaN); // ''

  3. 复制代码

  • 参数为字符串,则转成数字
 
  1. 'ab'.repeat('ab'); // ''

  2. 'ab'.repeat('3'); // 'ababab'

  3. 复制代码

1.3.3 padStart(),padEnd()

用于将字符串头部尾部补全长度,padStart()头部补全padEnd()尾部补全
这两个方法接收2个参数,第一个指定字符串最小长度,第二个用于补全的字符串
基础用法 :

 
  1. 'x'.padStart(5, 'ab'); // 'ababx'

  2. 'x'.padEnd(5, 'ab'); // 'xabab'

  3. 复制代码

特殊用法:

  • 原字符串长度,大于或等于指定最小长度,则返回原字符串。
 
  1. 'xyzabc'.padStart(5, 'ab'); // 'xyzabc'

  2. 复制代码

  • 用来补全的字符串长度和原字符串长度之和,超过指定最小长度,则截去超出部分的补全字符串。
 
  1. 'ab'.padStart(5,'012345'); // "012ab"

  2. 复制代码

  • 省略第二个参数,则用空格补全。
 
  1. 'x'.padStart(4); // ' x'

  2. 'x'.padEnd(4); // 'x '

  3. 复制代码

1.3.4 模版字符串

用于拼接字符串,ES6之前:

 
  1. let a = 'abc' +

  2. 'def' +

  3. 'ghi';

  4. 复制代码

ES6之后:

 
  1. let a = `

  2. abc

  3. def

  4. ghi

  5. `

  6. 复制代码

拼接变量: 在**反引号(`)**中使用${}包裹变量或方法。

 
  1. // ES6之前

  2. let a = 'abc' + v1 + 'def';

  3.  
  4. // ES6之后

  5. let a = `abc${v1}def`

  6. 复制代码

1.4 正则的拓展

1.4.1 介绍

在ES5中有两种情况。

  • 参数是字符串,则第二个参数为正则表达式的修饰符。
 
  1. let a = new RegExp('abc', 'i');

  2. // 等价于

  3. let a = /abx/i;

  4. 复制代码

  • 参数是正则表达式,返回一个原表达式的拷贝,且不能有第二个参数,否则报错。
 
  1. let a = new RegExp(/abc/i);

  2. //等价于

  3. let a = /abx/i;

  4.  
  5. let a = new RegExp(/abc/, 'i');

  6. // Uncaught TypeError

  7. 复制代码

ES6中使用:
第一个参数是正则对象,第二个是指定修饰符,如果第一个参数已经有修饰符,则会被第二个参数覆盖。

 
  1. new RegExp(/abc/ig, 'i');

  2. 复制代码

1.4.2 字符串的正则方法

常用的四种方法:match()replace()search()split()

1.4.3 u修饰符

添加u修饰符,是为了处理大于uFFFF的Unicode字符,即正确处理四个字节的UTF-16编码。

 
  1. /^\uD83D/u.test('\uD83D\uDC2A'); // false

  2. /^\uD83D/.test('\uD83D\uDC2A'); // true

  3. 复制代码

由于ES5之前不支持四个字节UTF-16编码,会识别为两个字符,导致第二行输出true,加入u修饰符后ES6就会识别为一个字符,所以输出false

注意:
加上u修饰符后,会改变下面正则表达式的行为:

  • (1)点字符 点字符(.)在正则中表示除了换行符以外的任意单个字符。对于码点大于0xFFFF的Unicode字符,点字符不能识别,必须加上u修饰符。
 
  1. var a = "?";

  2. /^.$/.test(a); // false

  3. /^.$/u.test(a); // true

  4. 复制代码

  • (2)Unicode字符表示法 使用ES6新增的大括号表示Unicode字符时,必须在表达式添加u修饰符,才能识别大括号。
 
  1. /\u{61}/.test('a'); // false

  2. /\u{61}/u.test('a'); // true

  3. /\u{20BB7}/u.test('?'); // true

  4. 复制代码

  • (3)量词 使用u修饰符后,所有量词都会正确识别码点大于0xFFFF的 Unicode 字符。
 
  1. /a{2}/.test('aa'); // true

  2. /a{2}/u.test('aa'); // true

  3. /?{2}/.test('??'); // false

  4. /?{2}/u.test('??'); // true

  5. 复制代码

  • (4)i修饰符 不加u修饰符,就无法识别非规范的K字符。
 
  1. /[a-z]/i.test('\u212A') // false

  2. /[a-z]/iu.test('\u212A') // true

  3. 复制代码

检查是否设置u修饰符: 使用unicode属性。

 
  1. const a = /hello/;

  2. const b = /hello/u;

  3.  
  4. a.unicode // false

  5. b.unicode // true

  6. 复制代码

1.4.4 y修饰符

y修饰符与g修饰符类似,也是全局匹配,后一次匹配都是从上一次匹配成功的下一个位置开始。区别在于,g修饰符只要剩余位置中存在匹配即可,而y修饰符是必须从剩余第一个开始。

 
  1. var s = 'aaa_aa_a';

  2. var r1 = /a+/g;

  3. var r2 = /a+/y;

  4.  
  5. r1.exec(s) // ["aaa"]

  6. r2.exec(s) // ["aaa"]

  7.  
  8. r1.exec(s) // ["aa"] 剩余 '_aa_a'

  9. r2.exec(s) // null

  10. 复制代码

lastIndex属性: 指定匹配的开始位置:

 
  1. const a = /a/y;

  2. a.lastIndex = 2; // 从2号位置开始匹配

  3. a.exec('wahaha'); // null

  4. a.lastIndex = 3; // 从3号位置开始匹配

  5. let c = a.exec('wahaha');

  6. c.index; // 3

  7. a.lastIndex; // 4

  8. 复制代码

返回多个匹配
一个y修饰符对match方法只能返回第一个匹配,与g修饰符搭配能返回所有匹配。

 
  1. 'a1a2a3'.match(/a\d/y); // ["a1"]

  2. 'a1a2a3'.match(/a\d/gy); // ["a1", "a2", "a3"]

  3. 复制代码

检查是否使用y修饰符
使用sticky属性检查。

 
  1. const a = /hello\d/y;

  2. a.sticky; // true

  3. 复制代码

1.4.5 flags属性

flags属性返回所有正则表达式的修饰符。

 
  1. /abc/ig.flags; // 'gi'

  2. 复制代码

1.5 数值的拓展

1.5.1 Number.isFinite(), Number.isNaN()

Number.isFinite() 用于检查一个数值是否是有限的,即不是Infinity,若参数不是Number类型,则一律返回false 。

 
  1. Number.isFinite(10); // true

  2. Number.isFinite(0.5); // true

  3. Number.isFinite(NaN); // false

  4. Number.isFinite(Infinity); // false

  5. Number.isFinite(-Infinity); // false

  6. Number.isFinite('leo'); // false

  7. Number.isFinite('15'); // false

  8. Number.isFinite(true); // false

  9. Number.isFinite(Math.random()); // true

  10. 复制代码

Number.isNaN()用于检查是否是NaN,若参数不是NaN,则一律返回false

 
  1. Number.isNaN(NaN); // true

  2. Number.isNaN(10); // false

  3. Number.isNaN('10'); // false

  4. Number.isNaN(true); // false

  5. Number.isNaN(5/NaN); // true

  6. Number.isNaN('true' / 0); // true

  7. Number.isNaN('true' / 'true'); // true

  8. 复制代码

区别
与传统全局的isFinite()isNaN()方法的区别,传统的这两个方法,是先将参数转换成数值,再判断。
而ES6新增的这两个方法则只对数值有效, Number.isFinite()对于非数值一律返回false,Number.isNaN()只有对于NaN才返回true,其他一律返回false

 
  1. isFinite(25); // true

  2. isFinite("25"); // true

  3. Number.isFinite(25); // true

  4. Number.isFinite("25"); // false

  5.  
  6. isNaN(NaN); // true

  7. isNaN("NaN"); // true

  8. Number.isNaN(NaN); // true

  9. Number.isNaN("NaN"); // false

  10. 复制代码

1.5.2 Number.parseInt(), Number.parseFloat()

这两个方法与全局方法parseInt()parseFloat()一致,目的是逐步减少全局性的方法,让语言更模块化

 
  1. parseInt('12.34'); // 12

  2. parseFloat('123.45#'); // 123.45

  3.  
  4. Number.parseInt('12.34'); // 12

  5. Number.parseFloat('123.45#'); // 123.45

  6.  
  7. Number.parseInt === parseInt; // true

  8. Number.parseFloat === parseFloat; // true

  9. 复制代码

1.5.3 Number.isInteger()

用来判断一个数值是否是整数,若参数不是数值,则返回false

 
  1. Number.isInteger(10); // true

  2. Number.isInteger(10.0); // true

  3. Number.isInteger(10.1); // false

  4. 复制代码

1.5.4 Math对象的拓展

ES6新增17个数学相关的静态方法,只能在Math对象上调用。

  • Math.trunc:
    用来去除小数的小数部分,返回整数部分
    若参数为非数值,则先转为数值
    若参数为空值无法截取整数的值,则返回NaN
 
  1. // 正常使用

  2. Math.trunc(1.1); // 1

  3. Math.trunc(1.9); // 1

  4. Math.trunc(-1.1); // -1

  5. Math.trunc(-1.9); // -1

  6. Math.trunc(-0.1234); // -0

  7.  
  8. // 参数为非数值

  9. Math.trunc('11.22'); // 11

  10. Math.trunc(true); // 1

  11. Math.trunc(false); // 0

  12. Math.trunc(null); // 0

  13.  
  14. // 参数为空和无法取整

  15. Math.trunc(NaN); // NaN

  16. Math.trunc('leo'); // NaN

  17. Math.trunc(); // NaN

  18. Math.trunc(undefined); // NaN

  19. 复制代码

ES5实现

 
  1. Math.trunc = Math.trunc || function(x){

  2. return x < 0 ? Math.ceil(x) : Math.floor(x);

  3. }

  4. 复制代码

  • Math.sign():
    判断一个数是正数负数是零,对于非数值,会先转成数值
    返回值:
    • 参数为正数, 返回 +1
    • 参数为负数, 返回 -1
    • 参数为0, 返回 0
    • 参数为-0, 返回 -0
    • 参数为其他值, 返回 NaN
 
  1. Math.sign(-1); // -1

  2. Math.sign(1); // +1

  3. Math.sign(0); // 0

  4. Math.sign(-0); // -0

  5. Math.sign(NaN); // NaN

  6.  
  7. Math.sign(''); // 0

  8. Math.sign(true); // +1

  9. Math.sign(false);// 0

  10. Math.sign(null); // 0

  11. Math.sign('9'); // +1

  12. Math.sign('leo');// NaN

  13. Math.sign(); // NaN

  14. Math.sign(undefined); // NaN

  15. 复制代码

ES5实现

 
  1. Math.sign = Math.sign || function (x){

  2. x = +x;

  3. if (x === 0 || isNaN(x)){

  4. return x;

  5. }

  6. return x > 0 ? 1: -1;

  7. }

  8. 复制代码

  • Math.cbrt():
    用来计算一个数的立方根,若参数为非数值则先转成数值。
 
  1. Math.cbrt(-1); // -1

  2. Math.cbrt(0); // 0

  3. Math.cbrt(1); // 1

  4. Math.cbrt(2); // 1.2599210498

  5.  
  6. Math.cbrt('1'); // 1

  7. Math.cbrt('leo'); // NaN

  8. 复制代码

ES5实现

 
  1. Math.cbrt = Math.cbrt || function (x){

  2. var a = Math.pow(Math.abs(x), 1/3);

  3. return x < 0 ? -y : y;

  4. }

  5. 复制代码

  • Math.clz32():
    用于返回一个数的 32 位无符号整数形式有多少个前导 0。
 
  1. Math.clz32(0) // 32

  2. Math.clz32(1) // 31

  3. Math.clz32(1000) // 22

  4. Math.clz32(0b01000000000000000000000000000000) // 1

  5. Math.clz32(0b00100000000000000000000000000000) // 2

  6. 复制代码

  • Math.imul():
    用于返回两个数以 32 位带符号整数形式相乘的结果,返回的也是一个 32 位的带符号整数。
 
  1. Math.imul(2, 4) // 8

  2. Math.imul(-1, 8) // -8

  3. Math.imul(-2, -2) // 4

  4. 复制代码

  • Math.fround():
    用来返回一个数的2位单精度浮点数形式。
 
  1. Math.fround(0) // 0

  2. Math.fround(1) // 1

  3. Math.fround(2 ** 24 - 1) // 16777215

  4. 复制代码

  • Math.hypot():
    用来返回所有参数的平方和的平方根
 
  1. Math.hypot(3, 4); // 5

  2. Math.hypot(3, 4, 5); // 7.0710678118654755

  3. Math.hypot(); // 0

  4. Math.hypot(NaN); // NaN

  5. Math.hypot(3, 4, 'foo'); // NaN

  6. Math.hypot(3, 4, '5'); // 7.0710678118654755

  7. Math.hypot(-3); // 3

  8. 复制代码

  • Math.expm1():
    用来返回ex - 1,即Math.exp(x) - 1
 
  1. Math.expm1(-1) // -0.6321205588285577

  2. Math.expm1(0) // 0

  3. Math.expm1(1) // 1.718281828459045

  4. 复制代码

ES5实现

 
  1. Math.expm1 = Math.expm1 || function(x) {

  2. return Math.exp(x) - 1;

  3. };

  4. 复制代码

  • Math.log1p():
    用来返回1 + x的自然对数,即Math.log(1 + x)。如果x小于-1,返回NaN
 
  1. Math.log1p(1) // 0.6931471805599453

  2. Math.log1p(0) // 0

  3. Math.log1p(-1) // -Infinity

  4. Math.log1p(-2) // NaN

  5. 复制代码

ES5实现

 
  1. Math.log1p = Math.log1p || function(x) {

  2. return Math.log(1 + x);

  3. };

  4. 复制代码

  • Math.log10():
    用来返回以 10为底的x的对数。如果x小于 0,则返回 NaN
 
  1. Math.log10(2) // 0.3010299956639812

  2. Math.log10(1) // 0

  3. Math.log10(0) // -Infinity

  4. Math.log10(-2) // NaN

  5. Math.log10(100000) // 5

  6. 复制代码

ES5实现

 
  1. Math.log10 = Math.log10 || function(x) {

  2. return Math.log(x) / Math.LN10;

  3. };

  4. 复制代码

  • Math.log2():
    用来返回以 2 为底的x的对数。如果x小于0,则返回 NaN
 
  1. Math.log2(3) // 1.584962500721156

  2. Math.log2(2) // 1

  3. Math.log2(1) // 0

  4. Math.log2(0) // -Infinity

  5. Math.log2(-2) // NaN

  6. Math.log2(1024) // 10

  7. Math.log2(1 << 29) // 29

  8. 复制代码

ES5实现

 
  1. Math.log2 = Math.log2 || function(x) {

  2. return Math.log(x) / Math.LN2;

  3. };

  4. 复制代码

  • 双曲函数方法:
    • 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)

1.5.5 指数运算符

新增的指数运算符(**):

 
  1. 2 ** 2; // 4

  2. 2 ** 3; // 8

  3.  
  4. 2 ** 3 ** 2; // 相当于 2 ** (3 ** 2); 返回 512

  5. 复制代码

指数运算符(**)与Math.pow的实现不相同,对于特别大的运算结果,两者会有细微的差异。

 
  1. Math.pow(99, 99)

  2. // 3.697296376497263e+197

  3.  
  4. 99 ** 99

  5. // 3.697296376497268e+197

  6. 复制代码

1.6 函数的拓展

1.6.1 参数默认值

 
  1. // ES6 之前

  2. function f(a, b){

  3. b = b || 'leo';

  4. console.log(a, b);

  5. }

  6.  
  7. // ES6 之后

  8. function f(a, b='leo'){

  9. console.log(a, b);

  10. }

  11.  
  12. f('hi'); // hi leo

  13. f('hi', 'jack'); // hi jack

  14. f('hi', ''); // hi leo

  15. 复制代码

注意:

  • 参数变量是默认声明的,不能用letconst再次声明:
 
  1. function f (a = 1){

  2. let a = 2; // error

  3. }

  4. 复制代码

  • 使用参数默认值时,参数名不能相同:
 
  1. function f (a, a, b){ ... }; // 不报错

  2. function f (a, a, b = 1){ ... }; // 报错

  3. 复制代码

与解构赋值默认值结合使用

 
  1. function f ({a, b=1}){

  2. console.log(a,b)

  3. };

  4. f({}); // undefined 1

  5. f({a:2}); // 2 1

  6. f({a:2, b:3}); // 2 3

  7. f(); // 报错

  8.  
  9. function f ({a, b = 1} = {}){

  10. console.log(a, b)

  11. }

  12. f(); // undefined 1

  13. 复制代码

尾参数定义默认值:
通常在尾参数定义默认值,便于观察参数,并且非尾参数无法省略。

 
  1. function f (a=1,b){

  2. return [a, b];

  3. }

  4. f(); // [1, undefined]

  5. f(2); // [2, undefined]

  6. f(,2); // 报错

  7.  
  8. f(undefined, 2); // [1, 2]

  9.  
  10. function f (a, b=1, c){

  11. return [a, b, c];

  12. }

  13. f(); // [undefined, 1, undefined]

  14. f(1); // [1,1,undefined]

  15. f(1, ,2); // 报错

  16. f(1,undefined,2); // [1,1,2]

  17. 复制代码

在给参数传递默认值时,传入undefined会触发默认值,传入null不会触发。

 
  1. function f (a = 1, b = 2){

  2. console.log(a, b);

  3. }

  4. f(undefined, null); // 1 null

  5. 复制代码

函数的length属性:
length属性将返回,没有指定默认值的参数数量,并且rest参数不计入length属性。

 
  1. function f1 (a){...};

  2. function f2 (a=1){...};

  3. function f3 (a, b=2){...};

  4. function f4 (...a){...};

  5. function f5 (a,b,...c){...};

  6.  
  7. f1.length; // 1

  8. f2.length; // 0

  9. f3.length; // 1

  10. f4.length; // 0

  11. f5.length; // 2

  12. 复制代码

1.6.2 rest 参数

rest参数形式为(...变量名),其值为一个数组,用于获取函数多余参数。

 
  1. function f (a, ...b){

  2. console.log(a, b);

  3. }

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

  5. 复制代码

注意

  • rest参数只能放在最后一个,否则报错:
 
  1. function f(a, ...b, c){...}; // 报错

  2. 复制代码

  • 函数的length属性不包含rest参数。
 
  1. function f1 (a){...};

  2. function f2 (a,...b){...};

  3. f1(1); // 1

  4. f2(1,2); // 1

  5. 复制代码

1.6.3 name 属性

用于返回该函数的函数名。

 
  1. function f (){...};

  2. f.name; // f

  3.  
  4. const f = function g(){...};

  5. f.name; // g

  6. <
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值