标准开头
今天我们来看一下ES6的函数部分知识
函数
函数初始值
有时候,函数的非必填参数,我们可以给予其默认值。保证程序完整不会出错
在早期,我们赋初始值可能是这样做的:
// 早期ES5方法
function ajax(url, method, param) {
method = method ? method : 'GET';
param = param ? param : {};
console.log(url, method, param);
}复制代码
但是这种方法不够整洁和美观。且维护较为麻烦
在ES6中,我们可以直接在参数栏上指定默认值
function ajax(url, method = 'GET', param = {}) {
console.log(url, method, param)
}复制代码
这样让方法看起来更加整洁。且保证了程序的正常运行
我们可以用babel编译为ES5代码review一下:
'use strict';
function ajax(url) {
var method = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'GET';
var param = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
console.log(url, method, param);
}
ajax('http://www.baidu.com');复制代码
转换为ES5代码后,我们可以看出:其转换方法就是判断参数列表内是否有值且长度是否足够。然后再进行判断
函数剩余操作符
在对于很多重复参数的函数,我们可以用“...”剩余操作符进行省略
例如,我们现在有个方法,要把每个参数进行相加,参数可以随便定义长度。但是长度必须>2
在ES5中,我们可能要重复写好多的参数名。不仅造成浪费,也让程序易读性变差
function sum(param1, param2, param3, param4, param5) {
console.log(param1 + param2 + param3 + param4 + param5);
}复制代码
其实我们从param2 - param5可以借助ES6合并为同一个参数。且无需手动扩展
function sum(param1, ...paramN) {
let result = param1;
paramN.forEach((param) => {
result += param
});
console.log(result);
}复制代码
合并后的参数会输出为一个数组,大家可以按照数组的操作来操作它
函数参数解构
如果我们按照一个对象的方式当作参数传入一个函数,且函数参数也是对象的方式接受。那我们可以完成一次解构
还记得之前解构要怎么做吗?要保证解构双方的类型,数据格式要类似
function f({name, age}) {
console.log(name, age);
}
f({name: 'janlay', age: 8});复制代码
不难理解
箭头函数
箭头函数应该是ES6函数中最Nice的一个知识了。中文名叫“箭头函数”,英文名叫“Lambda表达式”。
箭头函数是为了在你声明方法时,更加简单便捷。其语法如下:
let sum = (a, b) => {
return a + b;
};复制代码
箭头左边的是参数列表,右边的就是函数方法体
当你的函数只有一个参数时,你可以更加简化函数方法
let result = num => num * 2;复制代码
但是当你使用箭头函数时,你可就小心咯。我们用箭头函数会涉及到一个叫“作用域”的问题。这个问题通常影响我们的关键字this的值
因为箭头函数内调用this,作用域并不是指向箭头函数本身,而是指向比箭头函数还要大一层的函数。举个栗子
let myInfo = {
name: 'janlay',
sayHello: () => {
console.log(`Hi,My name is ${this.name}`)
}
};
myInfo.sayHello();复制代码
这时候控制台输出undefined
正如我们所说的,箭头函数内的this会指向它上一层函数中的作用域。但是他并没有上一层函数体。所以我们打印this,也是显示undefined
简述深浅拷贝
先上这样一段代码
let myInfo = {
name: 'janlay',
age: 17
};
let heInfo = {};
heInfo = myInfo;
heInfo.name = 'Mike';
console.log(myInfo);复制代码
按照一般逻辑,我们复制一份myInfo到heInfo。然后我们修改heInfo内的属性,输出myInfo应该不会变才对
但是我们错了
{ name: 'Mike', age: 17 }复制代码
像这种对象拷贝叫做 “浅拷贝”。意味着只是拷贝了内存地址,但是并没有再内存中复制一份给新变量
像这样的浅拷贝,还有ES6的“Object.assign()”方法。他的作用是传入2个对象进行合并,然后赋值给第三个对象。
有时候我们会用到浅拷贝,但是一般情况下我们要用到深拷贝。也就是我们常说的值传递
深拷贝的方式很多。由于本人学识有限,给大家带来一个容易理解的深拷贝方法
1. JSON.parse()和JSON.stringify方法
这应该算是最简单的深拷贝方法了。其原理就是将源对象转化为一个JSON对象,然后用parse方法再释放为一个对象。经过这么一折腾,内存地址就发生了改变。也就达到了深拷贝的效果
let myInfo = {
name: 'janlay',
age: 17
};
let heInfo = {};
heInfo = JSON.parse(JSON.stringify(myInfo));
heInfo.name = 'Mike';
console.log(myInfo);复制代码
结果输出为: { name: 'janlay', age: 17 }
2. 使用外置clone方法
其原理也很简单,通过遍历对象,让对象的每个值都挨个复制给新对象,不再进行整体复制。细分到对象的最小单位
function clone(origin) {
let newObj = {}; //新对象
for (let key in origin) { //循环原始对象
if (typeof origin[key] === 'object') { //如果对象内的属性是一个对象
newObj[key] = clone(origin[key]) // 用递归方式对对象内的对象进行拆分
} else { //否则
newObj[key] = origin[key]; //如果是简单的属性,直接复制
}
}
return newObj; //返回拷贝后的新对象
}复制代码
调用 heInfo = clone(myInfo);
结果输出为 { name: 'janlay', age: 17 }
以上两种深拷贝方法都非常简单。像了解更深度的深拷贝,这里推荐一个掘金的另一篇文章