TOC
ECMAScript 6 简介
ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
数值的扩展
二进制和八进制表示法
- 基本用法:
ES6 提供了二进制和八进制数值的新的写法,分别用前缀
0b(或0B)
和0o(或0O)
表示。 如果要将0b
和0o
前缀的字符串数值转为十进制,要使用Number
方法。0b111110111 === 503 // true 0o767 === 503 // true Number('0b111') // 7 Number('0o10') // 8
Number 对象的扩展
Number.isFinite(), Number.isNaN()
-
基本用法:
Number.isFinite()
: 用来检查一个数值是否为有限的(finite),即不是Infinity
。如果参数类型不是数值,Number.isFinite
一律返回false
。Number.isNaN()
:用来检查一个值是否为NaN。如果参数类型不是NaN
,Number.isNaN
一律返回false
。
-
和全局方法
isFinite()
和isNaN()
的区别:isFinite()
和isNaN()
: 先调用Number()
将非数值的值转为数值,再进行判断。Number.isFinite()
: 只对数值有效, 对于非数值一律返回false
。Number.isNaN()
:只对数值有效, 只有对于NaN
才返回true
,非NaN
一律返回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 Number.isNaN(1) // false
Number.parseInt(), Number.parseFloat()
- 基本用法:
ES6 将全局方法
parseInt()
和parseFloat()
,移植到Number
对象上面,行为完全保持不变。 这样做的目的,是逐步减少全局性方法,使得语言逐步模块化。// ES5的写法 parseInt('12.34') // 12 parseFloat('123.45#') // 123.45 // ES6的写法 Number.parseInt('12.34') // 12 Number.parseFloat('123.45#') // 123.45
Number.isInteger()
- 基本用法:
Number.isInteger()
用来判断一个数值是否为整数。
Number.EPSILON
- 基本用法:
ES6 在
Number
对象上面,新增一个极小的常量Number.EPSILON
。根据规格,它表示 1 与大于 1 的最小浮点数之间的差。Number.EPSILON
实际上是 JavaScript 能够表示的最小精度。误差如果小于这个值,就可以认为已经没有意义了,即不存在误差了。 引入一个这么小的量的目的在于为浮点数计算设置一个误差范围。我们知道浮点数计算是不精确的。
安全整数 和 Number.isSafeInteger()
- 基本用法:
JavaScript 能够准确表示的整数范围在
-2^53
到2^53
之间(不含两个端点),超过这个范围,无法精确表示这个值。ES6 引入了Number.MAX_SAFE_INTEGER
和Number.MIN_SAFE_INTEGER
这两个常量,用来表示这个范围的上下限。Number.isSafeInteger()
则是用来判断一个整数是否落在这个范围之内。
Math 对象的扩展
Math.trunc()
- 基本用法:
Math.trunc
方法用于去除一个数的小数部分,返回整数部分。
Math.sign()
- 基本用法:
Math.sign
方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。它会返回五种值:- 参数为正数,返回+1
- 参数为负数,返回-1
- 参数为 0,返回0
- 参数为-0,返回-0
- 其他值,返回NaN
Math.cbrt(),Math.hypot()
- 基本用法:
Math.cbrt
方法用于计算一个数的立方根。Math.hypot
方法返回所有参数的平方和的平方根。
Math.clz32()
- 基本用法:
Math.clz32()
方法将参数转为 32 位无符号整数的形式,然后返回这个 32 位值里面有多少个前导 0。
Math.imul()
- 基本用法:
Math.imul
方法返回两个数以 32 位带符号整数形式相乘的结果,返回的也是一个 32 位的带符号整数。
Math.fround()
- 基本用法:
Math.fround
方法返回一个数的32位单精度浮点数形式。
对数方法: Math.expm1(), Math.log1p(), Math.log10(), Math.log2()
- 基本用法:
Math.expm1(x)
返回ex - 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小于 0,则返回
NaN`。
双曲函数方法: Math.sinh(), Math.cosh(), Math.tanh(), Math.asinh(), Math.acosh(), Math.atanh()
- 基本用法:
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)
指数运算符
- 基本用法:
ES2016 新增了一个指数运算符(
**
)。2 ** 2 // 4 2 ** 3 // 8
函数的扩展
函数参数的默认值
- 基本用法:
ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面。参数变量是默认声明的,所以不能用
let
或const
再次声明。 参数默认值不是传值的,而是每次都重新计算默认值表达式的值。也就是说,参数默认值是惰性求值
的。function log(x, y = 'World') { console.log(x, y); } log('Hello') // Hello World log('Hello', 'China') // Hello China log('Hello', '') // Hello //与解构赋值默认值结合使用 function foo({x, y = 5} = {}) { console.log(x, y); } foo() // undefined 5
- 作用域: 一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域(context)。等到初始化结束,这个作用域就会消失。这种语法行为,在不设置参数默认值时,是不会出现的。
函数的 length 属性
- 基本用法:
指定了默认值以后,函数的
length
属性,将返回没有指定默认值的参数个数。也就是说,指定了默认值后,length
属性将失真。 这是因为length
属性的含义是,该函数预期传入的参数个数。某个参数指定默认值以后,预期传入的参数个数就不包括这个参数了。(function (a) {}).length // 1 (function (a = 5) {}).length // 0 (function (a, b, c = 5) {}).length // 2 //函数的length属性,不包括 rest 参数。 (function(...args) {}).length // 0 //如果设置了默认值的参数不是尾参数,那么length属性也不再计入后面的参数了。 (function (a = 0, b, c) {}).length // 0 (function (a, b = 1, c) {}).length // 1
rest 参数
- 基本用法:
ES6 引入
rest
参数(形式为...变量名
:rest参数)(...
:扩展运算符),用于获取函数的多余参数,这样就不需要使用arguments
对象了。rest
参数搭配的变量是一个数组,该变量将多余的参数放入数组中。 注意,rest
参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。function add(...values) { let sum = 0; for (var val of values) { sum += val; } return sum; } add(2, 5, 3) // 10
name 属性
- 基本用法:
函数的
name
属性,返回该函数的函数名。这个属性早就被浏览器广泛支持,但是直到 ES6,才将其写入了标准。function foo() {} foo.name // "foo" //将一个匿名函数赋值给一个变量 var f = function () {}; // ES5 f.name // "" // ES6 f.name // "f" //将一个具名函数赋值给一个变量 const bar = function baz() {}; // ES5 bar.name // "baz" // ES6 bar.name // "baz" //Function构造函数返回的函数实例,name属性的值为anonymous。 (new Function).name // "anonymous" //bind返回的函数,name属性值会加上bound前缀。 function foo() {}; foo.bind({}).name // "bound foo" (function(){}).bind({}).name // "bound "
箭头函数
- 基本用法:
ES6 允许使用“箭头”(
=>
)定义函数。var f = v => v; // 等同于 var f = function (v) { return v; }; //如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。 var f = () => 5; // 等同于 var f = function () { return 5 }; 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" }); // 不报错
- 使用注意点:
- 函数体内的
this
对象,就是定义时所在的对象,而不是使用时所在的对象。箭头函数让this
指向固定化。 - 不可以当作构造函数,也就是说,不可以使用
new
命令,否则会抛出一个错误。 - 不可以使用
arguments
对象,该对象在函数体内不存在。如果要用,可以用rest 参数
代替。 - 不可以使用
yield
命令,因此箭头函数不能用作Generator
函数。
- 函数体内的
严格模式
-
基本用法: 从 ES5 开始,函数内部可以设定为严格模式(
'use strict'
)。 ES2016 做了一点修改,规定只要函数参数使用了默认值
、解构赋值
、或者扩展运算符
,那么函数内部就不能显式设定为严格模式,否则会报错。 这样规定的原因是,函数内部的严格模式同时适用于函数体和函数参数。但是,函数执行的时候,先执行函数参数,然后再执行函数体。这样就有一个不合理的地方,只有从函数体之中,才能知道参数是否应该以严格模式执行,但是参数却应该先于函数体执行。function doSomething(a, b) { 'use strict'; // code } // 报错 function doSomething(a, b = a) { 'use strict'; // code } // 报错 const doSomething = function ({a, b}) { 'use strict'; // code }; // 报错 const doSomething = (...a) => { 'use strict'; // code };
两种方法可以规避这种限制:
//第一种是设定全局性的严格模式 'use strict'; function doSomething(a, b = a) { // code } //第二种是把函数包在一个无参数的立即执行函数里面。 const doSomething = (function () { 'use strict'; return function(value = 42) { return value; }; }());
尾调用优化
- 基本用法:
尾调用(Tail Call)
是函数式编程的一个重要概念,指某个函数的最后一步是调用另一个函数。函数调用会在内存形成一个调用记录
,又称调用帧(call frame)
。尾调用优化(Tail call optimization)
,即只保留内层函数的调用帧。 如果所有函数都是尾调用,那么完全可以做到每次执行时,调用帧只有一项,这将大大节省内存。这就是尾调用优化
的意义。 ES6 的尾调用优化
只在严格模式下开启,正常模式是无效的。这是因为在正常模式下,函数内部有两个变量,可以跟踪函数的调用栈。func.arguments
:返回调用时函数的参数。func.caller
:返回调用当前函数的那个函数。 尾调用优化发生时,函数的调用栈会改写,因此上面两个变量就会失真。严格模式禁用这两个变量,所以尾调用模式仅在严格模式下生效。 注意,目前只有 Safari 浏览器支持尾调用优化,Chrome 和 Firefox 都不支持。
尾递归
- 基本用法: 函数调用自身,称为递归。如果尾调用自身,就称为尾递归。尾递归的实现,往往需要改写递归函数,确保最后一步只调用自身。做到这一点的方法,就是把所有用到的内部变量改写成函数的参数。
函数参数的尾逗号
- 基本用法:
ES2017 允许函数的最后一个参数有尾逗号(trailing comma)。
function clownsEverywhere( param1, param2, ) { /* ... */ }
Function.prototype.toString()
- 基本用法:
ES2019 对函数实例的
toString()
方法做出了修改。toString()
方法返回函数代码本身,以前会省略注释和空格。修改后的toString()
方法,明确要求返回一模一样的原始代码。function /* foo comment */ foo () {} //ES5: foo.toString() // function foo() {} //ES6: foo.toString() // "function /* foo comment */ foo () {}"
catch 命令的参数省略
- 基本用法:
JavaScript 语言的
try...catch
结构,以前明确要求catch
命令后面必须跟参数,接受try
代码块抛出的错误对象。ES2019 做出了改变,允许catch
语句省略参数。try { // ... } catch { // ... }
「下次一定」
下次一定
使用微信扫描二维码完成支付