阅读 90

了解一下ES6: 函数&简述深浅拷贝

标准开头


今天我们来看一下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 }


以上两种深拷贝方法都非常简单。像了解更深度的深拷贝,这里推荐一个掘金的另一篇文章

 深拷贝的终极探索(90%的人都不知道)


The End

Babel中文网 - ES6在线转换ES5工具


关注下面的标签,发现更多相似文章
评论