首页 > 技术文章 > 箭头函数、rest参数与扩展运算符

qingshanyici 2019-04-03 22:47 原文

一、基本用法

箭头函数的基本语法是:

var 函数名=(参数1,参数2)=>{要执行的函数操作};

例如一下两端代码进行函数声明的功能是一样的:

var f1=(num1,num2)=>{
    console.log(num1+num2);
}
var f2=function(num1,num2){
    console.log(num1+num2);
}
f1(1,2);//3
f2(3,4);//7

 

 

箭头函数也可以与对象混合使用。注意变量的属性需要用花括号括起来。基本语法如下:

var 变量名=({变量属性1,变量属性2})=>{对变量属性的操作};

var person={
    name:'Alice',
    age:18,
}
var f1=({name,age})=>{console.log('f11-->'+name+age);}
function f2(person){
    console.log('f2-->'+person.name,person.age);
}

f1(person);//f11-->Alice18
f2(person);//f2-->Alice 18

 

 

二、箭头函数的作用

箭头函数的作用就是简化回调函数。

var arr=[1,2,3];
arr.map(function(x){
    console.log(x*x);//1,4,9
})
arr.map(x=>{console.log(x*x)});//1,4,9

 

 

三、rest参数

虽然叫做reset参数,但实际上写法是...变量名。作用是获取函数的多余参数。比如下面这段代码,要加的数值全都用...values代替了。而values的数量可以是任意数量,values是一个数组。

function add(...values){
    let sum=0;
    for(let val of values){
        sum=sum+val;
    }
    console.log(sum);
}
add(1,2,3);//6

 注意,reset参数只能作为最后一个参数传入方法中,也就是说reset参数后面不能再有其他的参数了。否则会报错。

这里还有一个要注意的地方,就是for of 与 for in的区别。

for in 主要是操作对象的。

 

四、箭头函数与rest参数的混合使用

var object1=(head,...tail)=>{
    console.log([head,tail]);
}
object1(1,"one","two","three");//[1, Array(3)]

 

五、扩展运算符

1、对象的扩展运算符

对象中的扩展运算符 用于 取出参数对象中的所有可遍历属性,拷贝到当前对象之中。

let bar = {a: 1, b: 2}
let baz = {...bar}
//等同于
let bar = {a: 1, b: 2}
let baz = Object.assign({}, bar)

 

如果有同名属性,会被覆盖

let bar = {a: 1, b: 2}
let obj = {a: 3, b: 4}
let baz = {...bar, ...obj}
console.log("baz-->>", baz) //{a: 3, b: 4}
console.log("bar-->>", bar) //{a:1, b: 2}

 

扩展运算符对于对象实例的拷贝是浅拷贝。JS中有两种数据类型:基础数据类型和引用数据类型。

基础数据类型是按照值来进行访问的,常见的基础数据类型有Number、Sting、Boolean、Null和Undefined,这类变量拷贝的时候会完整的复制一份。

引用数据类型,如Array,在拷贝的时候拷贝的是对象的引用,当原对象发生变化的时候,拷贝对象也跟着变化。

let obj1= {a:1, b:2}
let obj2 = {...obj1, b:'2-edited'}
console.log('obj1-->>', obj1) //{a: 1, b: 2}
console.log('obj2-->>', obj2) // {a:1, b: '2-edited'}
obj2['b'] = 3
console.log("obj2-->>", obj2) //{a: 1, b: 3} 

这个例子,扩展运算符拷贝的对象是基础数据类型,因此对obj2的修改并不会影响到obj1。但如果改成这样:

let obj1 = { a: 1, b: 2, c: {nickName: 'd'}};
let obj2 = { ...obj1};
obj2.c.nickName = 'd-edited';
console.log(obj1); // {a: 1, b: 2, c: {nickName: 'd-edited'}}
console.log(obj2); // {a: 1, b: 2, c: {nickName: 'd-edited'}}

 

由于拷贝的是对象的引用,当原对象发生变化的时候,拷贝对象也跟着变化。 obj1中的对象c是一个引用数据类型,拷贝的时候,拷贝的是 对象的引用。

 

2、数组的扩展运算符

(1)将数组转化为参数序列:

function add(x, y) {
    return x + y;
  }
  const numbers = [4, 38];
  add(...numbers) // 42
  

 

 

(2)由于浅复制的原因,直接复制数组是难以实现的,因为会影响拷贝对象,比如:

var arr1 = [1,2]
var arr2 = arr1
console.log("arr2-->>", arr2) //[1, 2]
arr2[0] = '改变第一项'
console.log("arr1-->>", arr1) //['改变第一项', 2]

 

但是用扩展运算符就能是实现:

var arr1 = [1, 2]
var arr2 = [...arr1]

 

因为 扩展运算符用于 取出参数对象中的所有可遍历属性,拷贝到当前对象之中。 由于该数组里面的所有对象都是基础数据类型,因此不存在浅拷贝的现象。

但如果这样,浅复制了一个引用数据类型,并对引用数据类型进行操作,就会影响原来的数组了。

var arr1 = [1, [3,4]]
var arr2 = [...arr1]
arr2[1] [0]= '第二项改变'
console.log("arr1-->>", arr1, arr1[1]) //[1, ['第二项改变',4]]

 

 

(3)扩展运算符与解构赋值结合起来,可以生成数组

let [first, ...rest] = [1,2,3,4,5]
console.log("first-->>", first, typeof first) //1 number
console.log("rest-->>", rest) //[2,3,4,5] array

 

注意,rest参数只能放在最后一位。否则报错。

 

(4)字符串转数组

[...'hello']
// [ "h", "e", "l", "l", "o" ]

 

推荐阅读