es6入门(一)

一、定义变量

1.1 使用let定义变量

语法格式:

let 变量名 [= 变量值]

let和var的区别?

1)let声明变量的作用域只在当前代码块中有效,而var可以在代码块中使用,也可以在全局范围内使用;
2)let声明的变量必须要先声明后使用,否则报错,而var会返回undefined,不会报错;
3)在同一个代码块中使用let声明的变量不允许出现重复;
4)var声明的全局变量是保存在顶层对象window中,而let声明的全局变量不是保存在window对象中,而是保存在globalThis对象中;

一般在全局环境中获取顶层对象都是通过this变量来获取。但是,this在不同语言环境的作用可能不相同。比如在Node或ES6中,this返回的是当前模块。后台ECMA引入globalThis作为顶层对象。也就是说,任何环境下,globalThis都是存在的,都可以从它拿到顶层对象,指向全局环境下的this。

例如:

<script>
	// 定义变量,只在当前代码块中有效
	let a = 10
	//alert("a = " + a);
	
	// 定义常量,一旦定义就无法改变它的值
	const b = 10
	
	//b = 20 
	//alert("b = " + b)
	
	let sayHello = function() {
		alert("hello es6")
	}
	
	sayHello()
</script>

注意:ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。

1.2 使用const定义变量

语法格式:

const 变量名 = 变量值

let与const的区别

1)const声明的变量不得改变值,而let声明的变量可以改变它的值;
2)const声明变量的时候必须要初始化,而let不需要;

注意:如果const变量类型是引用类型,const只能够保证变量这个指针地址是固定的,而不能够保证她指向的数据结构是否可变。因此,使用const声明对象的时候必须要小心。

例如:

<script>
	const user = {
		id : 110,
		name : 'jacky'
	}
	
	// 下面注释代码报错
	/*user = {
		id : 220,
		name : 'mickey'
	}*/
	
	user.id = 220
	
	alert(user.id)
</script>

二、变量解构(Destructuring)

2.1 数组解构

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。例如:

<script>
	let arr = [10, 20, 30]
	let [a, b, c] = arr
	alert("a = " + a + ", b = " + b + ", c = " + c)
</script>

上面代码同时声明a、b、c三个变量,它们的值为数组arr下标为0、1、2的三个元素的值。

也可以不完全解构,例如:

<script>
	let [a, b, c] = [ , , 30]
	alert("a = " + a + ", b = " + b + ", c = " + c)
</script>

上面代码输出结果为:a = undefined, b = undefined, c = 30

另一种情况是不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。例如:

<script>
	let [a, b, c] = [10, 20, 30, 50, 99]
	alert("a = " + a + ", b = " + b + ", c = " + c)
</script>

上面代码属于不完全解构,但也能够解构成功。输出结果为:a = 10, b = 20, c = 30

注意:如果等号的右边不是数组,或者严格来说不是可遍历的结构,那么就会报错。例如:

<script>
	let [a] = 10
</script>

上面的语句都会报错,因为等号右边的值,要么转为对象以后不具备 Iterator 接口。控制台提示错误信息:

Uncaught TypeError: 10 is not iterable

2.2 默认值

<script>
	let [a = 10] = []  // a = 10
	let [x, y = 'b'] = ['a'];   // x = 'a', y = 'b'
</script>

注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。例如:

<script>
	let [a = 10] = [undefined]  // a = 10
	let [x, y = 'b'] = [null];   // x = null, y = 'b'
</script>

上面第二行代码的数组成员是null,默认值就不会生效,因为null不严格等于undefined。

默认值还可以是表达式,例如:

<script>
	function f() {
	  return 10
	}
	
	let [x = f()] = [1]	
	alert(x)  //  x = 1
	
	let [x = f()] = []	
	alert(x)  //  x = 10
</script>

如果x能取到值,所以函数f()不会被执行。

默认值可以引用解构赋值的其他变量,但该变量必须已经声明。

<script>
	let [x = 1, y = x] = []         // x=1; y=1
	let [x = 1, y = x] = [2]        // x=2; y=2
	let [x = 1, y = x] = [1, 2]     // x=1; y=2
	let [x = y, y = 1] = []         // ReferenceError: y is not defined
</script>

2.3 对象解构

解构不仅可以用于数组,还可以用于对象。例如:

<script>
	let { foo, bar } = {bar: 'bbb', foo: 'aaa'}
	alert(bar)
</script>

对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

<script>
	let { foo, baz } = {bar: 'bbb', foo: 'aaa'}
	alert(baz)  // undefined
</script>

上面代码没有baz变量的定义,所以解构失败,变量的值等于undefined。

如果变量名和属性名不一致,那么在变量名前面需要指定模式,模式就是关联对象的属性名。例如:

let { foo: baz } = { foo: 'aaa', bar: 'bbb' };

上面baz前面指定关联对象的foo属性。所以baz变量的值为aaa。

与数组一样,解构也可以用于嵌套结构的对象。例如:

<script>
	let obj = {
	  p: [
	    'Hello',
	    { y: 'World' }
	  ]
	};
	
	let {p: [x, { y }]} = obj;
</script>

上面代码中变量x的值为hello,y的值为world。

注意:上面代码最后一行的p是模式,不是变量,因此不会被赋值。如果想p也要作为变量赋值,可以写成:

let {p, p: [x, { y }]} = obj;

对象的解构赋值也可以取到继承的属性。

<script>
	const obj1 = {};
	const obj2 = { foo: 'bar' };
	// obj1继承了obj2的原型
	Object.setPrototypeOf(obj1, obj2);
	const { foo } = obj1;
	alert(foo)  // 这里输出bar
</script>

上面代码中,对象obj1的原型对象是obj2。foo属性不是obj1自身的属性,而是继承自obj2的属性,解构赋值可以取到这个属性。

Object.setPrototypeOf()ECMAScript 6最新草案中的方法,用于设置一个指定的对象的原型到另一个对象。相对于 Object.prototype,它被认为是修改对象原型更合适的方法。

注意事项:
1)如果要将一个已经声明的变量用于解构赋值,必须非常小心。例如:

let x;
{x} = {x: 1};

上面代码会报错。因为 JavaScript 引擎会将{x}理解成一个代码块。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。例如:

let x;
({x} = {x: 1});

2)解构赋值允许等号左边的模式之中,不放置任何变量名。例如:

({} = [true, false]);
({} = 'abc');
({} = []);

上面的代码不会报错,但是没有任何意义。

3)由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。例如:

<script>
	let arr = [1, 2, 3];
	let {0 : first, [arr.length - 1] : last} = arr;
</script>

上面变量first的值为1,last的值为3。

2.4 字符串解构

字符串也可以解构赋值。这时候字符串被转换成了一个类似数组的对象。例如:

const [a, b, c, d, e] = 'hello';
let {length : len} = 'hello';

上面代码变量len的值为字符串hello的length属性的值。

2.5 函数解构

函数的参数也可以使用解构赋值。例如:

function add([x, y]){
  return x + y;
}

add([1, 2]); // 3

上面代码中,函数add的参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量x和y。对于函数内部的代码来说,它们能感受到的参数就是x和y。

2.6 解构赋值的应用场景

(1)交换变量的值

<script>
	let x = 1;
	let y = 2;
	[x, y] = [y, x];
</script>

(2)从函数返回多个值
如果函数返回多个值,除了可以把它们放在数组或对象里面以外,还可以使用解构赋值。例如:

<script>
	function f() {
	  return [1, 2, 3];
	}
	let [a, b, c] = f();
</script>

变量的值为:a = 1, b = 2, c = 3

<script>
	function example() {
	  return {
	    foo: 1,
	    bar: 2
	  };
	}
	let { foo, bar } = example();
</script>

变量的值为:foo = 1, bar = 2

(3)函数参数定义
解构赋值可以方便地将一组参数与变量名对应起来。

// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);

// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});

(4)提取json数据

解构赋值可以快速提取 JSON 数据的值。

<script>
	let jsonData = {
	  id: 42,
	  status: "OK",
	  data: [867, 5309]
	};
	
	let {id, status, data} = jsonData;
	console.log(id, status, data);
</script>

除了上面这些用途以外,结构函数还可以给函数参数默认值,遍历Map结构,加载模块指定方法等。

三、字符串扩展

ES6 对字符串进行了改造和增强。

3.1 字符的 Unicode 表示法

ES6 加强了对 Unicode 的支持,允许采用\uxxxx形式表示一个字符,其中xxxx表示字符的 Unicode 码点。例如:

"\u0061" 表示字符‘a’

但是,这种表示法只限于码点在\u0000~\uFFFF之间的字符。超出这个范围的字符,必须用两个双字节的形式表示。

"\u20BB7" 表示“空格 + 7”

上面代码表示,如果直接在\u后面跟上超过0xFFFF的数值(比如\u20BB7),JavaScript 会理解成\u20BB+7。由于\u20BB是一个不可打印字符,所以只会显示一个空格,后面跟着一个7。

ES6 对这一点做出了改进,只要将码点放入大括号,就能正确解读该字符。例如:

"\u{20BB7}"

3.2 增加字符串遍历接口

for (let c of 'foo') {
  console.log(c)
}

除了遍历字符串,这个遍历器最大的优点是可以识别大于0xFFFF的码点,传统的for循环无法识别这样的码点。例如:

let text = String.fromCodePoint(0x20BB7);

for (let i = 0; i < text.length; i++) {
  console.log(text[i]);
}
// " "
// " "

for (let i of text) {
  console.log(i);
}
// "?"

上面代码中,字符串text只有一个字符,但是for循环会认为它包含两个字符(都不可打印),而for…of循环会正确识别出这是一个字符。

3.3 模板字符串

模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串。例如:

// 普通字符串
`In JavaScript '\n' is a line-feed.`

// 多行字符串
`In JavaScript this is
 not legal.`

如果使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中。

注意:如果在模板字符串中需要使用反引号,则前面要用反斜杠转义。例如:

let greeting = `\`Yo\` World!`;

可以在模板字符串中使用嵌入变量。模板字符串中嵌入变量,需要将变量名写在${}之中。

// 字符串中嵌入变量
let name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

注意:1)如果大括号中的值是一个对象,将默认调用对象的toString方法;2)如果模板字符串中的变量没有声明,将报错;

也可以在模板字符串中调用函数。

function fn() {
  return "Hello World";
}

`foo ${fn()} bar`

模板字符串还可以嵌套。

const tmpl = addrs => `
  <table>
  ${addrs.map(addr => `
    <tr><td>${addr.first}</td></tr>
    <tr><td>${addr.last}</td></tr>
  `).join('')}
  </table>
`;

const data = [
    { first: '<Jane>', last: 'Bond' },
    { first: 'Lars', last: '<Croft>' },
];

console.log(tmpl(data));

3.4 标签模板(tagged template)

模板字符串的功能,不仅仅是上面这些。它可以紧跟在一个函数名后面,该函数将被调用来处理这个模板字符串。

alert`123`
// 等同于
alert(123)

但是,如果模板字符里面有变量,就不是简单的调用了,而是会将模板字符串先处理成多个参数,再调用函数。

let a = 5;
let b = 10;

tag`Hello ${ a + b } world ${ a * b }`;

// tag函数定义
function tag(stringArr, value1, value2){
  ...
}

上面tag函数调用等同于:

tag(['Hello ', ' world ', ''], 15, 50);

tag函数的第一个参数是一个数组,该数组的成员是模板字符串中那些没有变量替换的部分,比如:['Hello ', ’ world ', ‘’]。从第二个参数开始是模板字符串各个变量被替换后的值。因此,value1的值为15, value2的值为50。

3.5 字符串新增方法

3.5.1 String.raw方法

ES6 还为原生的 String 对象,提供了一个raw()方法。该方法返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串,往往用于模板字符串的处理方法。例如:

String.raw('hello world\n')

如果原字符串的斜杠已经转义,那么String.raw()会进行再次转义。

String.raw()方法可以作为处理模板字符串的基本方法,它会将所有变量替换,而且对斜杠进行转义,方便下一步作为字符串来使用。例如:

<script>
	let aa = (name) => String.raw`hello ${name}\n`
	let bb = aa('jacky')
	alert(bb)
</script>

如果String.raw()方法也可以作为正常的函数使用。这时,它的第一个参数,应该是一个具有raw属性的对象,且raw属性的值应该是一个数组。例如:

String.raw({ raw: 'test' }, 0, 1, 2);
// 等同于
String.raw({ raw: ['t','e','s','t'] }, 0, 1, 2);

上面String.raw函数返回“t0e1s2t”。

3.5.2 includes, startsWith, endsWith函数

传统上,JavaScript 只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6 又提供了三种新方法。

  • includes():返回布尔值,表示是否找到了参数字符串;
  • startsWith():返回布尔值,表示参数字符串是否在原字符串的头部;
  • endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部;

例如:

<script>
	let s = 'Hello world!';
	
	console.log(s.startsWith('Hello')) // true
	console.log(s.endsWith('!')) // true
	console.log(s.includes('o')) // true
</script>

这三个方法都支持第二个参数,表示开始搜索的位置。例如:

<script>
	let s = 'Hello world!';
	
	console.log(s.startsWith('Hello', 6)) // false
	console.log(s.endsWith('!', 5)) // false
	console.log(s.includes('o', 6)) // true
</script>

上面代码表示,使用第二个参数n时,endsWith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束。

3.5.3 repeat函数

repeat方法返回一个新字符串,表示将原字符串重复n次。例如:

<script>
	let s = 'x'.repeat(3)
	alert(s);  // "xxx"
</script>

注意事项:

  • 如果参数是0,则返回空;
  • 如果参数是小数,会被取整;
  • 如果参数是小于-1的负数或Infinity,则报错;
  • 如果参数是0到-1之间的小数,则取整后就变成0。
  • 如果参数是字符串,则会先转换成数字。

3.5.4 padStart、padEnd

ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。

'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'

'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'

如果原字符串的长度,等于或大于最大长度,则字符串补全不生效,返回原字符串。

'xxx'.padStart(2, 'ab') // 'xxx'
'xxx'.padEnd(2, 'ab') // 'xxx'

如果用来补全的字符串与原字符串,两者的长度之和超过了最大长度,则会截去超出位数的补全字符串。

'abc'.padStart(10, '0123456789') // '0123456abc'

如果省略第二个参数,默认使用空格补全长度。

3.5.5 trimStart、trimEnd

ES2019 对字符串实例新增了trimStart()和trimEnd()这两个方法。它们的行为与trim()一致,trimStart()消除字符串头部的空格,trimEnd()消除尾部的空格。它们返回的都是新字符串,不会修改原始字符串。

const s = '  abc  ';

s.trim() // "abc"
s.trimStart() // "abc  "
s.trimEnd() // "  abc"

除了空格键,这两个方法对字符串头部(或尾部)的 tab 键、换行符等不可见的空白符号也有效。

3.5.6 matchAll

matchAll()方法返回一个正则表达式在当前字符串的所有匹配。不过,它返回的是一个遍历器(Iterator),而不是数组。

<script>
	const regex = /\b[a-z]{5}\b/ig 
	const s = 'hello javax hello php hello vue'
	
	// 返回所有匹配的迭代器对象
	let itr = s.matchAll(regex)
	
	// 把迭代器转成数组
	let arr = [...itr]
	// 遍历数组
	for (var i in arr) {
		document.write(arr[i] + '<br/>')
	}
</script>

四、正则表达式扩展

4.1 增加正则修饰符

(1)u修饰符

(2)i修饰符

(3)y修饰符

(4)s修饰符

五 数值的扩展

5.1 进制表示法

ES6 提供了二进制和八进制数值的新的写法,分别用前缀0b(或0B)和0o(或0O)表示。如果要将0b和0o前缀的字符串数值转为十进制,要使用Number方法。

Number(0b0101)  // 将二进制转换成十进制
Number(0o10) // 将八进制转换成十进制

5.2 Number.isFinite、Number.isNaN

Number.isFinite():用来检查一个数值是否为有限的(finite),即不是Infinity。如果是有限的,则返回true,否则返回false。

Number.isFinite(15); // true
Number.isFinite(0.8); // true
Number.isFinite(NaN); // false
Number.isFinite(Infinity); // false
Number.isFinite(-Infinity); // false
Number.isFinite('foo'); // false
Number.isFinite('15'); // false
Number.isFinite(true); // false

注意:如果参数不是数值,则返回false。

Number.isNaN():用来检查一个数值是否为NaN。如果是有限的,则返回true,否则返回false。

Number.isNaN(NaN) // true
Number.isNaN(15) // false
Number.isNaN('15') // false
Number.isNaN(true) // false
Number.isNaN(9/NaN) // true
Number.isNaN('true' / 0) // true
Number.isNaN('true' / 'true') // true

如果参数类型不是NaN,Number.isNaN一律返回false。

5.3 Number.parseInt、Number.parseFloat

传统javascript的parsetInt和parseFloat方法是保存在全局window对象中。而ES6将它们移植到了Number对象中。这样做的目的,是逐步减少全局性方法,使得语言逐步模块化。

// ES5的写法
parseInt('12.34') // 12
parseFloat('123.45#') // 123.45

// ES6的写法
Number.parseInt('12.34') // 12
Number.parseFloat('123.45#') // 123.45

六、函数扩展

6.1 函数默认值

ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面。例如:

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
foo({x: 1}) // 1 5
foo({x: 1, y: 2}) // 1 2
foo() // TypeError: Cannot read property 'x' of undefined

如果函数foo调用时没提供参数,变量x和y就不会生成,从而报错。通过提供函数参数的默认值,就可以避免这种情况。

function foo({x, y = 5} = {}) {
  console.log(x, y);
}

foo() // undefined 5

上面代码指定,如果没有提供参数,函数foo的参数默认为一个空对象。

另外一个值得注意的地方,定义默认值的参数应该是尾参数。例如:

function f(x = 1, y) {
  return [x, y];
}

f() // [1, undefined]
f(2) // [2, undefined])
f(, 1) // 报错
f(undefined, 1) // [1, 1]

6.2 函数的length属性

函数length属性返回函数参数个数,当时不包含指定了默认值的参数,也不包含rest参数。例如:

(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2
(function(...args) {}).length // 0

如果设置了默认值的参数不是尾参数,那么length属性也不再计入后面的参数了。

(function (a = 0, b, c) {}).length // 0
(function (a, b = 1, c) {}).length // 1

6.3 Rest参数

ES6 引入 rest 参数(形式为…变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

// 求和
function add(...values) {
	let sum = 0
	for (var i in values) {
		sum += values[i]
	}
	return sum;
}

注意:Rest参数之后不能够再有其他参数,否则报错。

6.4 严格模式

从 ES5 开始,函数内部可以设定为严格模式。

function foo() {
	`use strict`
}

ES2016 做了一点修改,规定只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错。

// 报错
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
}

另外一种方法:是把函数包在一个无参数的立即执行函数里面。

let doSomething = (function() {
	'use strict'
	return function(a, b = a) {
		// code
	}
})

6.5 箭头函数

与java一样,es6开始支持使用箭头函数。

var f = function(v) {
	return v;
}

// 使用箭头函数替换
var f = v => v;

如果箭头函数不需要参数,或者有多个参数,使用圆括号括起来。

var f = () => 5;
var sum = (a, b) => a + b;

如果箭头函数体部分有多条语句,那么使用大括号括起来,并使用return语句返回。

var sum = (a, b) = {return a + b}

如果箭头函数返回一个对象,那么必须在对象外面使用大括号括起来。

let foo = (id, name) => ({stuId: id, stuName: name})

箭头函数可以与结构函数一起使用。

function(person) {
	return person.firstName + "" + person.lastName;
}

// 箭头函数和变量解构结合使用
const full = ({firstName, lastName}) => firstName + "" + lastName;

箭头函数的一个用处是简化回调函数。

var values = [21, 12, 9, 10, 13];
var result = values.sort(function (a, b) {
  return a - b;
});

// 使用箭头函数代替
var result = values.sort((a, b) => a - b);

使用箭头函数的注意点:

  • 箭头函数体中并没有this对象,所以在箭头函数中使用this,该this就是定义时所在对象;
// ES6
function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

// ES5
function foo() {
  var _this = this;

  setTimeout(function () {
    console.log('id:', _this.id);
  }, 100);
}
  • 箭头函数不可作为构造函数使用;
  • 箭头函数体中没有arguments对象,所以在箭头函数中使用arguments,实际上该arguments是箭头函数所在函数的arguments对象。
function foo() {
  setTimeout(() => {
    console.log('args:', arguments);
  }, 100);
}

foo(2, 4, 6, 8)  // args: [2, 4, 6, 8]
  • 不可以使用yield命令;

箭头函数不适合场景:

  • 定义对象方法时候,如果方法体中使用了this,那么不适用使用箭头函数定义;
const cat = {
  lives: 9,
  jumps: () => {
    this.lives--;
  }
}

上面jumps方法中的this代表全局对象,不是cat对象。

  • 需要动态this的时候,也不应使用箭头函数;
var button = document.getElementById('press');
button.addEventListener('click', () => {
  this.classList.toggle('on');
});

上面代码运行时,点击按钮会报错,因为button的监听函数是一个箭头函数,导致里面的this就是全局对象。如果改成普通函数,this就会动态指向被点击的按钮对象。

另外,如果函数体很复杂,有许多行,或者函数内部有大量的读写操作,不单纯是为了计算值,这时也不应该使用箭头函数,而是要使用普通函数,这样可以提高代码可读性。

6.6 函数参数的尾逗号

ES2017 允许函数的最后一个参数有尾逗号(trailing comma)。

function foo(
	param1,
	param2,
)

foo(
	'aa',
	'bb',
)

这样的规定也使得,函数参数与数组和对象的尾逗号规则,保持一致了。

6.7 catch命令的参数省略

JavaScript 语言的try…catch结构,以前明确要求catch命令后面必须跟参数,接受try代码块抛出的错误对象。

try {
  // ...
} catch (err) {
  // 处理错误
}

但是很多时候,catch代码块可能用不到这个参数。但是,为了保证语法正确,还是必须写。ES2019 做出了改变,允许catch语句省略参数。

try {
  // ...
} catch {
  // ...
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章