接下来我们来聊一聊一些ES6新增的语法
1、默认参数
以前,我们设置默认参数是这样的
function foo(x, y) {
x = x || 10
y = y || 11
console.log(x + y);
}
foo(1, 2); // 3
// 输出什么?
foo(1, null);
foo(1);
相信这个很快你就知道答案:12,是的,y没传参就取默认值 11
那这个呢?
foo(1, 0);
输出什么?
输出 1 ? NoNoNo.... 还是输出12
因为你传入的0被认为是false,所以 y || 11 会取11,而不是不传入的值0,使用这个有点危险
所以,ES6就新增了一种语法来改进这个缺点
function foo(x = 10, y = 11) {
console.log(x + y);
}
我们调用时:
foo(1, 2); // 3
// x=1, y=11
foo(1); // 12
// x=1, y=0
foo(1, 0); // 1
// undefined 默认y没有传参
foo(1, undefined); // 12
// null会被强制转换为 0
foo(1, null); // 1
2、剩余参数
剩余参数语法允许我们 将一个不定量的参数表示为一个数组
let sum = function(...args) {
let total = 0;
args.forEach(function(item) {
total += item
});
return total;
}
console.log(sum(10, 20)); // 60
console.log(sum(10, 20, 30, 40)); // 100
剩余参数跟结构匹配
let arr = [10, 20, 30]
let [value, ...args] = arr
console.log(value); // 10
console.log(args); // [20, 30]
剩余参数还可以用于数组
let arr = [10, 20, 30]
let [...args] = arr
console.log(args); // [10, 20, 30]
arr[0] = 40
console.log(arr); // [ 40, 20, 30 ]
console.log(args); // [10, 20, 30]
args 的值没有跟着arr的改变而改变,所以这种复制方式一种浅复制
3、解构
解构赋值就是按照对应位置,对变量进行赋值
ES6中新增了一种语法,分别用于数组解构和对象结构
2.1 数组解构
以前我们想要把数组中每个元素分别赋值给变量,是这么做的:
let arr = [1, 2, 3]
let a = arr[0],
b = arr[1],
c = arr[2]
console.log(a, b, c); // 1 2 3
利用数组结构相当方便
let arr = [1, 2, 3]
let [a, b, c] = arr
console.log(a, b, c); // 1 2 3
- 按照一一对应的关系匹配数组中的元素
2.2 对象解构
使用变量的名称匹配对象的属性,匹配成功将对象属性的值赋值给变量
let person = {
namer: '张三',
age: 2,
sex: '其它'
}
let { namer, age, sex } = person
console.log(namer, age, sex); // 张三 2 其它
注意:变量和属性名要匹配,换成别的变量会报错
还可以利用对象结构将属性值赋值给其它变量
let { namer: newName, age: newAge, sex: newSex } = person
console.log(newName, newAge, newSex); // 张三 2 其它
重复赋值
let { a: x, a: y } = { a: 100 }
console.log(x, y); // 100 100
4、对象字面量扩展
4.1 简洁属性
下面这种利用对象字面量创建对象,添加键值对是比较常见的
let namer = '张三', age = 2
let obj = {
namer: namer,
age: age
}
console.log(obj); // { namer: '张三', age: 2 }
ES6为我们提供了一种简洁属性的写法
let let obj = {
namer,
age
}
console.log(obj); // { namer: '张三', age: 2 }
4.2 简洁方法
为对象添加函数,我们平时是这样做的
let obj = {
a: function() {
console.log(123);
}
}
obj.a() // 123
ES6简化了方法的写法
let obj = {
a() {
console.log(123);
}
}
obj.a() // 123
- 推荐这种写法
4.3 计算属性名
以前我们计算对象属性名只能在“外面”
let namer = 'user'
let obj = {}
obj[namer + 'Foo'] = function() {}
obj[namer + 'Bar'] = function() {}
console.log(obj); // { userFoo: [Function (anonymous)], userBar: [Function (anonymous)] }
ES6之后,我们可以这么做
let namer = 'user'
let obj = {
[namer + 'Foo']: function() {},
[namer + 'Bar']: function() {}
}
console.log(obj); // { userFoo: [Function (anonymous)], userBar: [Function (anonymous)] }
5、箭头函数
当我们的函数比较简短的时候,可以使用ES6新增的箭头函数
语法:
() => {}
- 函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号
// 普通函数
function foo(x, y) {
console.log(x, y);
}
// 箭头函数
let foo = (x, y) => {x + y};
console.log(foo(1, 2));
- 如果形参只有一个,形参的小括号也可以省略
// 普通函数
function fn(n1) {
return n1 ** 2;
};
console.log(fn(2)); // 4
// 箭头函数
const fn1 = n1 => n1 ** 2;
console.log(fn1(2)); // 4
- 箭头函数不绑定
this关键字,箭头函数中没有this关键字,指向的是函数定义位置的上下文this
let obj = {
namer: '张三'
}
function foo() {
return () => {
console.log(this.namer);
}
}
// call 修改this的指向,并执行函数
let f = foo.call(obj);
f(); // 张三
箭头函数不能使用
argument、super和new.target,也不能用作构造函数,除此之外,箭头函数还没有prototype属性 —— 《JavaScript高级程序设计》
试一试
var age = 100;
var obj = {
name: 'zxc',
age: 18,
say: () => {
console.log(this.age);
}
};
obj.say();
结果输出什么?
100,我们说过,this指向的是其上一级函数,否则它就是指向全局作用域window;跟obj对象没有半毛钱关系
6、for...of 循环
ES6在for 和 for...in 的基础上新增了 for...in循环,在迭代器产生的一系列值上循环
for...of 必须的值必须是一个 iterable
先来看一下 for...in 循环
let arr = ['a', 'b', 'c', 'd']
// 遍历数组
for (index in arr) {
console.log(index); // 0 1 2 3
}
let obj = {
namer: '张三',
age: 2,
sex: '其它'
}
// 遍历对象
for (key in obj) {
console.log(key); // namer age sex
}
再来看看 for...of
let arr = ['a', 'b', 'c', 'd']
for (value of arr) {
console.log(value); // a b c d
}
所以:
for...in:遍历遍历的索引、对象的属性名for...of:遍历数组的值
for...of 一样可以用来遍历字符串
let str = 'hello'
for (value of str) {
console.log(value); // h e l l o
}
for...of循环也可以通过break、continue、return