ES6扩展了很多语法糖语法
其中对于函数我们又可以使用一种叫做“箭头函数”的写法
同时引入了Rest参数
利用“…”可以获取多余参数
这样就我们就不要使用arguments对象了
下面我来详细地谈一谈
函数默认参数
ES6没有出现之前
面对默认参数会让很多人感到痛苦
大家会采用各种hack
比如arr = arr || []
现在要容易得多
function foo(name = 'payen'){
console.log('my name is ' + name);
}
foo(); //my name is payen
只需要在参数列表中像赋值一样
就可以使用默认参数
Rest参数
当一个函数的最后一个参数有“…”这样的前缀
它就会变成一个参数的数组
为了让大家更好的理解
先来回忆一下我们以前ES6之前使用的arguments
function foo(){
var args = Array.prototype.slice.call(arguments);
console.log(args);
}
foo(1, 2, 3);// [1, 2, 3]
这里我先使用Array原型上的slice把arguments类数组
变成了真正的数组
然后打印这个参数数组
现在我们使用ES6的Rest参数
代码可已修改为这样
function foo(...args){
console.log(args);
}
foo(1, 2, 3);// [1, 2, 3]
确实要简洁很多
注意Rest参数与arguments有以下几点区别
①Rest参数是未指定变量名的参数数组
arguments是全部参数的集合
②Rest参数是真正的数组
arguments对象只是有length属性的类数组
展开操作符
上面我们提到了“…”操作符
包括我之前写到的解构赋值语法
都用到了它
它是ES6的新特性
然而它的强大不只如此
“…”叫做展开操作符
允许一个表达式在某处展开,用于
存在多个参数(函数调用)、多个元素(数组)、多个变量(解构赋值)
下面我就把除了Rest参数以外的用法总结一下
函数调用
想一想我们在ES6之前
如何将数组拆分作为参数传入函数
var arr = [1, 2, 3];
function demo(x, y, z){
console.log(x, y, z);
}
demo.apply(null, arr);// 1 2 3
利用apply来达到目的
看起来怪怪的
而现在我们可以这样做
let arr = [1, 2, 3];
function demo(x, y, z){
console.log(x, y, z);
}
demo(...arr);// 1 2 3
数组字面量
ES6之前我们想要拼接数组
可以使用concat()
var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var arr = arr1.concat(arr2);
console.log(arr);// [1, 2, 3, 4, 5, 6]
利用展开操作符就不需要调用这个方法了
var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var arr = [...arr1, ...arr2];
console.log(arr);// [1, 2, 3, 4, 5, 6]
箭头函数
箭头函数是一种更简单的函数声明方式
它永远是匿名函数
我们一般的函数写法
var sum = function(a, b){
return a + b;
};
箭头函数
let sum = (a, b) => {
return a + b;
};
当“箭头”后面是表达式的时候
还可以简化(省略“{ }”大括号 和 return关键字)
let sum = (a, b) => a + b;
略去function关键字
“=>”的前面是“( )”和内部的参数列表
“=>”的后面是代码块
回调函数
先来看看它在回调函数中应用它
var arr = [1, 2, 3];
console.log(arr.map((value)=>value*2));// [2, 4, 6]
不知道大家能不能看懂
它就相当于下面的代码
var arr = [1, 2, 3];
console.log(arr.map(function(value){
return value*2;
}));// [2, 4, 6]
返回对象
还有一点要注意
就是如果我们的函数只是返回一个对象
var foo = function(){
return {
name: 'payen'
}
}
使用箭头函数简化一步
let foo = () => {
return {
name: 'payen'
}
}
再简化一步
let foo = () => {name: 'payen'}; //错误的写法
这时我的编辑器提示语法问题了
这是应为它认为“=>”后面是一个代码块
而不会理解为是要返回的对象
解决办法仍然是使用万能的“( )”
这样编辑器、浏览器都会认为它是表达式了
let foo = () => ({name: 'payen'}); //正确的写法
this指向
嵌套函数就会产生this指向的问题
举个例子
var flag = 'global';
var obj = {
flag: 'object',
method: function(){
console.log(this.flag);
setTimeout(function(){
console.log(this.flag);
}, 200)
}
};
obj.method();//object global
即便把var声明全改为let也会输出 object undefined
第一个console.log不用说
对象的嵌套函数会指向全局window对象
method方法丢失了同this之间的绑定
这被认为是JavaScript在设计上的重大缺陷
我们一般都会采用一些hack来解决
使用临时缓存变量
借助于词法作用域
利用一个标识符self(通常起名self、that、_this)
(ES3)
var flag = 'global';
var obj = {
flag: 'object',
method: function(){
var self = this;
setTimeout(function(){
console.log(self.flag);
}, 200)
}
};
obj.method(); //object
或者利用bind()
(ES5)
/ES5
var flag = 'global';
var obj = {
flag: 'object',
method: function(){
setTimeout(function(){
console.log(this.flag);
}.bind(this), 200)
}
};
obj.method(); //object
现在使用箭头函数可以轻松解决问题
(ES6)
var flag = 'global';
var obj = {
flag: 'object',
method: function(){
setTimeout(()=>console.log(this.flag), 200);
}
};
obj.method(); //object
我们看到
箭头函数在涉及this绑定时的行为
与普通函数行为完全不同
它是用当前的此法作用域覆盖this本来的值
(“继承”了method()方法的this绑定)