重读《深入理解ES6》—— 函数

栏目: JavaScript · 发布时间: 5年前

内容简介:在 ES6 之前,JavaScript 的函数语法几乎没有发生太大的变化,而遗留的一些问题导致实现一些基本的功能经常要编写很多代码。而 ES6 对函数的大力度改进,让我们编写函数时更加方便且更少出错。而关于参数的处理以及箭头函数是我非常喜欢的功能。JavaScript 中的函数有一个比较特别的地方是形参和实参的数量可以不相同。当定义的形参没有默认值传入的时候,JavaScript 会为我们自动传入一个默认值。

在 ES6 之前,JavaScript 的函数语法几乎没有发生太大的变化,而遗留的一些问题导致实现一些基本的功能经常要编写很多代码。而 ES6 对函数的大力度改进,让我们编写函数时更加方便且更少出错。

而关于参数的处理以及箭头函数是我非常喜欢的功能。

一、函数形参的默认值

JavaScript 中的函数有一个比较特别的地方是形参和实参的数量可以不相同。当定义的形参没有默认值传入的时候,JavaScript 会为我们自动传入一个默认值。

在 ES5 的阶段,我们通常会自己设置一个默认值,就像下面这样:

function getAge(age) {
    age = age || 10;
    console.log(age);
}

getAge(12); // 12
getAge(0); // 10
复制代码

这段代码想告诉我们,当传入参数时,我们就取传入的值,如果没有传入,我们就取默认的 10。但是这通常会有一个问题,当我们传入一个 0 的时候,它也会被默认为一个假值,并最终将 age 赋值为 10。

在这种情况下,我们往往通过 typeof 检查参数类型,来实现相关功能:

function getAge(age) {
    age = (typeof age !== "undefined") ? age : 10;
    console.log(age);
}

getAge(12); // 12
getAge(0); // 10
复制代码

这种写法可以帮助我们更好地处理参数,但仔细想想,若是有多个参数时,这会让我们写许多额外的代码。幸好 ES6 参数默认值设置的出现,让我们可以很好的解决这个问题。

function getAge(age=10) {
    console.log(age);
}
getAge(); // 10,使用默认值
getAge(12); // 12,不使用默认值
getAge(0); // 0,不适用默认值,且传入参数为假值的情况
复制代码

值得注意的一点是:

function getAge(age=10, newAge=age) {
	console.log(newAge);
}
getAge(); // 10
复制代码

你可以把第二个参数的默认值设置为第一个参数,但是不能把第一个参数的默认值设置为第二个参数。

另一方面,函数的默认值还可以是一个表达式:

function getValue() {
    return 3;
}

function add(first, second=getValue()) {
    return first + second;
}

add(1, 3); // 4
add(2); // 5
复制代码

二、箭头函数

箭头函数是一个比较有趣的特性。因为简单的语法,大家工作中也经常用到,所以大家也比较熟悉,下面就简单说说箭头函数的语法。

箭头函数有1个参数,且函数体只有一条语句:

let f = value => value;

// 相当于

let f = function(value) {
    return value;
};
复制代码

箭头函数没有参数或者有多个参数,参数部分需要使用小括号:

let f = () => 20;
// 相当于 
let f = function() {
    return 20
};

let f = (a, b) => a + b;
// 相当于
let f = function(a, b) {
    return a + b;
}
复制代码

箭头函数的函数体内有多条语句:

let f = (a, b) => {
    return a * b;
};
复制代码

想让箭头函数返回一个对象字面量,需要将该字面量包裹在小括号里:

let f = () => ({ id: 1, name: 'zhangsan', age: 18 });

// 相当于

let f = function() {
    return {
        id: 1,
        name: 'zhangsan',
        age: 18
    };
}
复制代码

简单的介绍完箭头函数的基本语法,我们来看看箭头函数的一些主要特性:

1、箭头函数没有 this 绑定

箭头函数中没有 this 绑定,必须通过查找作用域链来决定其值。如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this ;否则, this 的值会被设置为全局对象。

或者再简单一点来说: 箭头函数的 this 指向离它最近的父级作用域

举个例子:

// 普通函数
let person = {
    name: 'zhangsan',
    age: 18,
    say: function() {
        console.log(this); // person 对象
        console.log(this.name); // 'zhangsan'
        console.log(this.age);  // 18
    }
};

person.say(); // 普通函数,谁调用,this 指向谁
复制代码
// 箭头函数
let person = {
    name: 'zhangsan',
    age: 18,
    say: () => {
        console.log(this); // window 对象
        console.log(this.name); // undefined
        console.log(this.age);  // undefined
    }
};

person.say(); // 箭头函数,没有 this,函数内部的 this,指向父级作用域,即全局
复制代码

最后,因为箭头函数中没有 this ,所以也不能用 call()、apply()、bind() 等方法改变 this 的指向。

2、箭头函数没有原型,不能通过 new 来调用

箭头函数的设计初衷是”即用即弃“,所以不能用它来定义新类型。所以,箭头函数中没有 prototype 属性,自然不能实例化,也就是不能用 new 关键字来调用。

let Person = () => {};
let p1 = new Person(); // Uncaught TypeError: Person is not a constructor

let Person = () => {};
console.log(Person.prototype); // undefined
复制代码

3、没有 argments 绑定

// 普通函数
let person = function() {
    console.log(arguments);
}
person(1); // 打印 arguments 对象
复制代码
// 箭头函数
let person = () => {
    console.log(arguments); 
}

person(1); // Uncaught ReferenceError: arguments is not defined
复制代码

总的来说,箭头函数和一些小特性的加入,可以使我们的编码更加方便。

友情链接

重读《深入理解ES6》 —— 块级作用域

重读《深入理解ES6》 —— 模板字符串

如果文章中错误或表述不严谨的地方,欢迎指正

也欢迎大家关注我的同名微信公众号:李等等扣丁

重读《深入理解ES6》—— 函数

以上所述就是小编给大家介绍的《重读《深入理解ES6》—— 函数》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

代码的未来

代码的未来

[日] 松本行弘 / 周自恒 / 人民邮电出版社 / 2013-6 / 79.00元

《代码的未来》是Ruby之父松本行弘的又一力作。作者对云计算、大数据时代下的各种编程语言以及相关技术进行了剖析,并对编程语言的未来发展趋势做出预测,内容涉及Go、VoltDB、node.js、CoffeeScript、Dart、MongoDB、摩尔定律、编程语言、多核、NoSQL等当今备受关注的话题。   《代码的未来》面向各层次程序设计人员和编程爱好者,也可供相关技术人员参考。一起来看看 《代码的未来》 这本书的介绍吧!

html转js在线工具
html转js在线工具

html转js在线工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具