在ES5与ES6环境下处理函数默认参数的实现方法


Posted in Javascript onMay 13, 2018

函数默认值是一个很提高鲁棒性的东西(就是让程序更健壮)

MDN关于函数默认参数的描述:函数默认参数允许在没有值或undefined被传入时使用默认形参。

ES5

使用逻辑或||来实现

众所周知,在ES5版本中,并没有提供的直接方法供我们我们处理函数默认值
所以只能够自己去增强函数的功能,一般会这么来做:

function doSomething (name, age) {
 name = name || 'default name'
 age = age || 18
 console.log(name, age)
}

我们将函数的两个参数name与age进行默认值的处理,如果没有则使用默认值。

在执行一下函数后,好像并没有什么不对:

doSomething()    // default name, 18
doSomething('Niko') // Niko    , 18
doSomething(, 12)  // default name, 12

然而当我们执行这样的代码时,就会获得一些超出预期的结果:

doSomething('Niko', 0) // Niko, 18

能够发现,对于参数0,我们上边的默认参数实现方法是有问题的

就像下边的四个表达式,都会输出wrong,这很显然不能够满足上边MDN关于函数默认参数的定义:

console.log(0     || 'wrong')
console.log(''    || 'wrong')
console.log(null   || 'wrong')
console.log(false   || 'wrong')

正确的姿势

所以,在ES5中正确的默认值处理应该是这样:

function doSomething (name, age) {
 if (name === undefined) {
  name = 'default name'
 }
 if (age === undefined) {
  age = 18
 }
 console.log(name, age)
}

使用三元运算符简化操作

或者我们简写成三元运算符形式的:

function doSomething (name, age) {
 name = name === undefined ? 'default name' : name
 age = age === undefined ? 18       : age
 console.log(name, age)
}

使用函数进行封装

但是如果我们每写一个函数,都要重复的去做这些操作
未免太麻烦了,所以,我们对这个逻辑进行一个简单的封装:

function defaultValue (val, defaultVal) {
 return val === undefined ? defaultVal : val
}
function doSomething (name, age) {
 name = defaultValue(name, 'default name')
 age = defaultValue(age , 18)
 console.log(name, age)
}

这样就很简洁的在ES5实现了函数默认参数的逻辑

one momre things

关于上边的defaultValue函数实现方法,我们在合理的使用弱类型语言的优势后
可以使用这种方式来省去三元运算符的操作:

function defaultValue () {
 return arguments[+(arguments[0] === undefined)]
}

我们知道,arguments表示函数所有的实参

我们使用arguments[0]获取第一个实参,然后与undefined进行全等比较

在外层将表达式的结果转换为Number,然后将这个值作为下标获取arguments中对应的参数。

因为是由Boolean值转变而来,所以只会存在0、1两种选项。

也就实现了上边三元运算符的功能。

ES6

ES6版本的函数默认值基本上就是我们上边实现的那种套路了

但是因为是原生的,所以会有相应的新语法,能够更简洁的使用:

function doSomething (name = 'default name', age = 18) {
 console.log(name, age)
}

ES6中提供了新的语法,可以让我们在函数声明参数后边直接写= [defaultValue]的这种形式来设置某个参数的默认值。
直接使用这种方式,省去了在函数内部进行默认值的检查,能够让函数专注的做它应该做的事情。

如何针对某些必填参数抛出异常

ES6这种新语法能够让我们很好的针对某个必填参数进行错误提醒:

function requireParams () {
 throw new Error('required params')
}
function doSomething (name = requireParams(), age = 18) {
 // do something
}

如果name参数为undefined,就会触发默认值规则

然后调用requireParams函数,而我们在函数中直接throw了一个Error

复杂结构参数的默认值处理

上边的处理都是针对简单的基本类型数据进行处理的,但如果我们有如下的一个函数:

function init ({id, value}) {}
init({
 id: 'tagId',
 value: 1
})

如果在ES5环境下,针对这种参数的默认值处理将会变得无比复杂

首先要判断这一个参数是否存在,然后在判断参数中的所有key是否存在

而在ES6中,可以这样来做:

function init ({
 id  = 'defaultId',
 value = 1
} = {}) {
 console.log(id, value)
}
init()

首先在解构函数的后边添加默认值= {},然后针对每一项参数添加默认值,很简洁的就实现了我们的需求。

ES5版本的polyfill代码在仓库中的位置:defaultValue

参考资料

1.MDN

总结

以上所述是小编给大家介绍的在ES5与ES6环境下处理函数默认参数的实现方法,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

Javascript 相关文章推荐
彻底搞懂JS无缝滚动代码
Jan 03 Javascript
jquery实现树形二级菜单实例代码
Nov 20 Javascript
浅析JavaScript原型继承的陷阱
Dec 03 Javascript
jQuery响应鼠标事件并隐藏与显示input默认值
Aug 24 Javascript
HTML的select控件美化
Mar 27 Javascript
详解Vue微信公众号开发踩坑全记录
Aug 21 Javascript
node中modules.exports与exports导出的区别
Jun 08 Javascript
微信小程序实现圆形进度条动画
Nov 18 Javascript
微信小程序换肤功能实现代码(思路详解)
Aug 25 Javascript
基于jquery实现彩色投票进度条代码解析
Aug 26 jQuery
vue使用swiper实现左右滑动切换图片
Oct 16 Javascript
如何用JavaScipt测网速
May 09 Javascript
vue中的$emit 与$on父子组件与兄弟组件的之间通信方式
May 13 #Javascript
node 命令方式启动修改端口的方法
May 12 #Javascript
安装Node.js并启动本地服务的操作教程
May 12 #Javascript
Node.js中,在cmd界面,进入退出Node.js运行环境的方法
May 12 #Javascript
Vue拖拽组件开发实例详解
May 11 #Javascript
node前端模板引擎Jade之标签的基本写法
May 11 #Javascript
JS实现的简单下拉框联动功能示例
May 11 #Javascript
You might like
PHP正则表达式之定界符和原子介绍
2012/10/05 PHP
php的mkdir()函数创建文件夹比较安全的权限设置方法
2014/07/28 PHP
ThinkPHP模板之变量输出、自定义函数与判断语句用法
2014/11/01 PHP
php同时使用session和cookie来保存用户登录信息的实现代码
2016/05/13 PHP
浅谈php处理后端&接口访问超时的解决方法
2016/10/29 PHP
jqgrid 简单学习笔记
2011/05/03 Javascript
JavaScript EasyPager 分页函数
2011/05/25 Javascript
Jquery实现列表(隔行换色,全选,鼠标滑过当前行)效果实例
2013/06/09 Javascript
js在数组中删除重复的元素自保留一个(两种实现思路)
2014/08/22 Javascript
jquery+ajax验证不通过也提交表单问题处理
2014/12/12 Javascript
javascript中call apply 的应用场景
2015/04/16 Javascript
JavaScript实现同一页面内两个表单互相传值的方法
2015/08/12 Javascript
谈谈基于iframe、FormData、FileReader三种无刷新上传文件的方法
2015/12/03 Javascript
JavaScript组合模式学习要点
2016/08/26 Javascript
IntersectionObserver API 详解篇
2016/12/11 Javascript
Node.js利用Net模块实现多人命令行聊天室的方法
2016/12/23 Javascript
详解Vue-基本标签和自定义控件
2017/03/24 Javascript
echarts学习笔记之箱线图的分析与绘制详解
2017/11/22 Javascript
在vue项目中引入highcharts图表的方法(详解)
2018/03/05 Javascript
微信公众号平台接口开发 菜单管理的实现
2019/08/14 Javascript
JavaScript实现简单计算器功能
2019/12/19 Javascript
JavaScript 俄罗斯方块游戏实现方法与代码解释
2020/04/08 Javascript
JS实现拖拽元素时与另一元素碰撞检测
2020/08/27 Javascript
[53:43]VP vs NewBee Supermajor 胜者组 BO3 第三场 6.5
2018/06/06 DOTA
[01:14]2019完美世界城市挑战赛(秋季赛)全国总决赛精彩花絮
2020/01/08 DOTA
Python爬虫之xlml解析库(全面了解)
2017/08/08 Python
将tf.batch_matmul替换成tf.matmul的实现
2020/06/18 Python
Python本地及虚拟解释器配置过程解析
2020/10/13 Python
Python eval函数原理及用法解析
2020/11/14 Python
日本快乐生活方式购物网站:Shop Japan
2018/07/17 全球购物
竞选体育委员演讲稿
2014/04/26 职场文书
2015年财务部年度工作总结
2015/05/19 职场文书
python中24小时制转换为12小时制的方法
2021/06/18 Python
Python移位密码、仿射变换解密实例代码
2021/06/27 Python
原生JavaScript实现简单五子棋游戏
2021/06/28 Javascript
使用Nginx+Tomcat实现负载均衡的全过程
2022/05/30 Servers