对于任何语言来说,函数都是一个重要的组成部分。在ES6以前,从JavaScript被创建以来,函数一直没有大的改动,留下了一堆的问题和很微妙的行为,导致在JavaScript中使用函数时很容易出现错误并且可能需要多余的代码实现一些基本的函数行为。在ES6中,函数有一个质的飞跃的改进,它充分考虑到过去数年间JavaScript开发者的需求和抱怨。与ES5相比,在ES6中使用函数开发不容易出错,而且更加灵活。

带默认参数的函数(Functions with Default Parameter Values)

在JavaScript中每个函数都是唯一的,函数不允许重载。不管函数声明时的参数有多少个,你都可以传入任意数量的实参。这允许你定义可以处理不同参数个数的函数,当参数没提供时,系统会使用默认的参数值。

在ES5中模拟默认参数值(Simulating Default Parameter Values in ECMAScript6)

在ES5或之前,通常如下创建一个带默认参数值的函数:

function makeRequest(url, timeout, callback) {
timeout = timeout || 2000;
callback = callback || function() {};
}

在这个例子中,通常timeout和callback是可选的参数,因为它们都可以使用默认的值。当第一个操作数为false时,或操作就会返回第二个操作数。因为函数如果没有提供形参对应的实参,形参会被设置为undefined,所以通常用或操作为未传入值的参数设置默认值。然而上面的这个函数可能会有问题,当timeout传入0时,timeout的值仍然会被赋值为2000。一个更安全的方法是检查参数的类型:

function makeRequest(url, timeout, callback) {
timeout = (typeof timeout !== "undefined") ? timeout : 2000;
callback = (typeof callback !== "undefined") ? callback : function () {};
}

尽管上面的方法更安全,但是需要更多的代码去执行一个基本的操作。

ES6中的默认参数值(Default Parameter Values in ECMAScript6)

在ES6中,你可以通过给形参初始化的方式轻松为形参提供默认值。第一个示例函数在ES6可以简单写成:

function makeRequest(url, timeout = 2000, callback = function() {}){
}

这个函数只有第一个函数参数是希望永远传递的,其他两个参数都有默认的值。与在ES5的写法相比,函数更小,因为你不需要任何额外的代码去检查缺失的参数值。当向makeRequest函数传递三个参数时,默认值都没被使用。下面是一些调用示例:

//使用默认的timeout和callback
makeRequest("/foo"); //使用默认的callback
makeRequest("/foo", 500); //不使用任何默认值
makeRequest("/foo", 500, function(body) {
doSomething(body);
});

实际上在ES6中,你可以为任何参数提供默认值,提供默认值的参数可以出现在未提供默认值的参数前面:

function makeRequest(url, timeout = 2000, callback) {
}

只有当你不传入第二个参数,或者第二个参数显示地传入undefined,第二个参数才会使用默认值:

//使用默认值
makeRequest("/foo", undefined, function(body) {
doSomething(body);
}); //使用默认值
makeRequest("/foo"); //不使用默认值
makeRequest("/foo", null, function(body) {
doSomething(body);
});

 默认参数值对arguments对象的影响(How Default Parameter Values Affect the arguments Object)

在右默认参数值的情况下,arguments对象的行为是不同的。在ES5中not-strict模式下,arguments对象可以反映函数参数的变化。下面是一个例子:

function mixArgs(first, second) {
console.log(first === arguments[0]);
console.log(second === arguments[1]);
first = "c";
second = "d";
console.log(first === arguments[0]);
console.log(second === arguments[1]);
} mixArgs("a", "b");

上面代码的输出结果如下:

true
true
true
true

在ES5中non-strict模式下,arguments对象总是会随着形参数值的变化而变化。因此给first和second两个参数的值更新后,后面两个比较仍然是true。在ES5中,如果使用strict模式,那么arguments就不会随着形参的变化而变化了。

在ES6中不管是strict模式还是non-strict模式,arguments对象的行为跟在ES5中使用strict模式一样。

来看下面的代码:

function mixArgs(first, second="b") {
console.log(arguments.length);
console.log(first === arguments[0]);
console.log(second === arguments[1]);
first = "c";
second = "d";
console.log(first === arguments[0]);
console.log(second == arguments[1]);
} mixArgs("a");

上面的代码输出如下:

1
true
false
false
false

因为向mixArgs函数只传了一个参数,所以arugments的长度为1。这也意味着arguments[1]是未定义的。所以前两个比较表达式的结果为true和false。后面改变first和second参数的值,arugments并未变化。因此后面两个比较表达式的结果都为false。在ES6中不管是strict还是non-strict模式中执行上面的代码,结果都是一样的。

默认参数表达式(Default Parameter Expressions)

实际上在ES6中,默认参数的值并不一定需要是一个确定的值,它可以是一个函数:

function getValue() {
return 5;
} function add(first, second = getValue()) {
return first + second;
} console.log(add(1, 1)); //
console.log(add(1)); //

不仅如此,前面的参数还可以作为后面参数的默认值:

function getValue(arg) {
return 5 + arg;
} function add(first, second = getValue(first)) {
return first + second;
} console.log(add(1, 1)); //
console.log(add(1)); //

当然后面的参数不能作为前面参数的默认值,否则程序会报错。

《理解 ES6》阅读整理:函数(Functions)(一)Default Parameter Values的更多相关文章

  1. Default Parameter Values in Python

    Python’s handling of default parameter values is one of a few things that tends to trip up most new ...

  2. [Python] Pitfalls: About Default Parameter Values in Functions

    Today an interesting bug (pitfall) is found when I was trying debug someone's code. There is a funct ...

  3. 《理解 ES6》阅读整理:函数(Functions)(三)Function Constructor & Spread Operator

    增强的Function构造函数(Increased Capabilities of the Function Constructor) 在Javascript中Function构造函数可以让你创建一个 ...

  4. 【Swift】 - 函数(Functions)总结 - 比较 与 C# 的异同

    1.0 函数的定义与调用( Defining and Calling Functions ) 习惯了C#了语法,看到下面的这样定义输入参数实在感到非常别扭,func 有点 Javascript的感觉, ...

  5. 《理解 ES6》阅读整理:函数(Functions)(五)Name Property

    名字属性(The name Property) 在JavaScript中识别函数是有挑战性的,因为你可以使用各种方式来定义一个函数.匿名函数表达式的流行使用导致函数调试困难,在栈信息中难以找出函数名. ...

  6. 深入理解ES6箭头函数中的this

    简要介绍:箭头函数中的this,指向与一般function定义的函数不同,比较容易绕晕,箭头函数this的定义:箭头函数中的this是在定义函数的时候绑定,而不是在执行函数的时候绑定. 1.何为定义时 ...

  7. Node.js模块导出module.exports 和 exports,Es6模块导出export 和export default的区别

    1.module.exports  module变量代表当前模块.这个变量是一个对象,module对象会创建一个叫exports的属性,这个属性的默认值是一个空的对象: module.exports ...

  8. JavaScript ES6中,export与export default

    自述: 本来是对new Vue()和export default比较懵的,查了一下,发现我理解错了两者的关系,也没意识到export与export default的区别,先简单的记录一下基本概念,后续 ...

  9. asp.net MVC helper 和自定义函数@functions小结

    asp.net Razor 视图具有.cshtml后缀,可以轻松的实现c#代码和html标签的切换,大大提升了我们的开发效率.但是Razor语法还是有一些棉花糖值得我们了解一下,可以更加强劲的提升我们 ...

随机推荐

  1. Bootstrap导航点击菜单跳转与点击缩放菜单折叠按钮缓冲效果插件jquery.singlePageNav.min.js

    引入步骤: <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></scrip ...

  2. 2016年 Delphi Roadmap

    2016年delphi Roadmap 发布,这也是新公司的第一次发布路线图. 虽然稍微晚点( 原来说是1月份发布路线图),至少比过去积极点.喧嚣多年的靴子终于落地. Linux 的支持终于正式公布. ...

  3. android开发 如何调用SO

    java package com.example.callsodemo; import android.R.integer; import android.R.string; import andro ...

  4. file access , argc, argv[ ]

    _____main函数含有 两个参数 ,argc ,argv[] 这两个参数用以指示命令行输入的参数信息. argc 的值是输入的参数的数量.argv是一个数组,每个数组元素指向一个string字符串 ...

  5. Android源代码结构分析

    Google提供的Android包含了:Android源代码,工具链,基础C库,仿真环境,开发环境等,完整的一套.第一级别的目录和文件如下所示:----------------├── Makefile ...

  6. timingFunction

    *  动画的开始与结束的快慢,有五个预置分别为(下同): *  kCAMediaTimingFunctionLinear            线性,即匀速 *  kCAMediaTimingFunc ...

  7. 获取WINDOW.OPEN url js中的get取值

    function getUrlParam(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)( ...

  8. linux 下搭建 storm

    搭建storm  需要搭建: 1.zookeeper 搭建 2.下载/安装 storm 的依赖包  zeromq, jzmq,python 2.storm 搭建 一.Zookeeper 安装 下载安装 ...

  9. Rsync+inotify实现实时同步

    1.1 inotify介绍 inotify是一种强大的.细粒度的.异步的文件系统事件控制机制.linux内核从2.6.13起,加入了inotify支持,通过inotify可以监控文件系统中添加.删除. ...

  10. POJ 2175 Evacuation Plan 费用流 负圈定理

    题目给了一个满足最大流的残量网络,判断是否费用最小. 如果残量网络中存在费用负圈,那么不是最优,在这个圈上增广,增广1的流量就行了. 1.SPFA中某个点入队超过n次,说明存在负环,但是这个点不一定在 ...