深入理解javascript函数系列第四篇——ES6函数扩展
前面的话
ES6标准关于函数扩展部分,主要涉及以下四个方面:参数默认值、rest参数、扩展运算符和箭头函数
参数默认值
一般地,为参数设置默认值需进行如下设置
- function log(x, y) {
- y = y || 'World';
- console.log(x, y);
- }
但这样设置实际上是有问题的,如果y的值本身是假值(包括false、undefined、null、''、0、-0、NaN),则无法取得本身值
- function log(x, y) {
- y = y || 'World';
- console.log(x, y);
- }
- log('Hello') // Hello World
- log('Hello', 'China') // Hello China
- log('Hello', NaN) // Hello World
ES6允许为函数的参数设置默认值,即直接写在参数定义的后面
- function log(x, y = 'World') {
- console.log(x, y);
- }
- log('Hello') // Hello World
- log('Hello', 'China') // Hello China
- log('Hello', NaN) // Hello NaN
[注意]参数变量是默认声明的,所以不能用let或const再次声明
- function foo(x = 5) {
- let x = 1; //SyntaxError: Identifier 'x' has already been declared
- const x = 2; //SyntaxError: Identifier 'x' has already been declared
- }
尾参数
通常情况下,定义了默认值的参数,应该是函数的尾参数。因为这样比较容易看出来,到底省略了哪些参数。如果非尾部的参数设置默认值,实际上这个参数是没法省略的
- function f(x = 1, y) {
- return [x, y];
- }
- f() // [1, undefined]
- f(2) // [2, undefined])
- f(, 1) // 报错
- f(undefined, 1) // [1, 1]
如果传入undefined,将触发该参数等于默认值,null则没有这个效果
- function foo(x = 5, y = 6) {
- console.log(x, y);
- }
- foo(undefined, null)// 5 null
length
指定了默认值以后,函数的length属性,将返回没有指定默认值的参数个数
- (function (a) {}).length //
- (function (a = 5) {}).length //
- (function (a, b, c = 5) {}).length //
[注意]如果设置了默认值的参数不是尾参数,那么length属性也不再计入后面的参数了
- (function (a = 0, b, c) {}).length //
- (function (a, b = 1, c) {}).length //
作用域
【1】如果参数默认值是一个变量,则该变量所处的作用域,与其他变量的作用域规则是一样的,即先是当前函数的作用域,然后才是全局作用域
- var x = 1;
- function f(x, y = x) {
- console.log(y);
- }
- f(2) //
【2】如果函数调用时,函数作用域内部的变量x没有生成,则x指向全局变量
- var x = 1;
- function f(y = x) {
- var x = 2;
- console.log(y);
- }
- f() //
应用
利用参数默认值,可以指定某一个参数不得省略,如果省略就抛出一个错误
- function throwIfMissing() {
- throw new Error('Missing parameter');
- }
- function foo(mustBeProvided = throwIfMissing()) {
- return mustBeProvided;
- }
- foo()// Error: Missing parameter
[注意]将参数默认值设为undefined,表明这个参数可以省略
- function foo(optional = undefined) {
- //todo
- }
rest参数
ES6引入rest参数(形式为“...变量名”),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中
- function add(...values) {
- var sum = 0;
- for (var val of values) {
- sum += val;
- }
- return sum;
- }
- add(2, 5, 3) //
rest参数中的变量代表一个数组,所以数组特有的方法都可以用于这个变量
下面是一个利用rest参数改写数组push方法的例子
- function push(array, ...items) {
- items.forEach(function(i) {
- array.push(i);
- console.log(i);
- });
- }
- var a = [];
- push(a, 1, 2, 3);
函数的length属性不包括rest参数
- (function(a) {}).length //
- (function(...a) {}).length //
- (function(a, ...b) {}).length //
[注意]rest参数之后不能再有其他参数
- //Uncaught SyntaxError: Rest parameter must be last formal parameter
- function f(a, ...b, c) {
- //todo
- }
扩展运算符
扩展运算符(spread)是三个点(...)。它好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列
- console.log(...[1, 2, 3])// 1 2 3
- console.log(1, ...[2, 3, 4], 5)// 1 2 3 4 5
- [...document.querySelectorAll('div')]// [<div>, <div>, <div>]
该运算符主要用于函数调用
- function add(x, y) {
- return x + y;
- }
- var numbers = [4, 38];
- add(...numbers) //
Math.max方法简化
- // ES5
- Math.max.apply(null, [14, 3, 77])
- // ES6
- Math.max(...[14, 3, 77])
- //等同于
- Math.max(14, 3, 77)
push方法简化
- // ES5
- var arr1 = [0, 1, 2];
- var arr2 = [3, 4, 5];
- Array.prototype.push.apply(arr1, arr2);
- // ES6
- var arr1 = [0, 1, 2];
- var arr2 = [3, 4, 5];
- arr1.push(...arr2);
扩展运算符可以将字符串转为真正的数组
- [...'hello']// [ "h", "e", "l", "l", "o" ]
箭头函数
关于箭头函数的详细介绍移步至此
参考资料
《ECMAScript 6入门》 阮一峰
深入理解javascript函数系列第四篇——ES6函数扩展的更多相关文章
- 深入理解javascript作用域系列第四篇——块作用域
× 目录 [1]let [2]const [3]try 前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用 ...
- 深入理解javascript作用域系列第四篇
前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用其他类型的作用域单元甚至可以实现维护起来更加优秀.简洁的 ...
- 深入理解javascript作用域系列第三篇——声明提升(hoisting)
× 目录 [1]变量 [2]函数 [3]优先 前面的话 一般认为,javascript代码在执行时是由上到下一行一行执行的.但实际上这并不完全正确,主要是因为声明提升的存在.本文是深入理解javasc ...
- 深入理解javascript作用域系列第三篇
前面的话 一般认为,javascript代码在执行时是由上到下一行一行执行的.但实际上这并不完全正确,主要是因为声明提升的存在.本文是深入理解javascript作用域系列第三篇——声明提升(hois ...
- 深入理解javascript函数进阶系列第四篇——惰性函数
前面的话 惰性函数表示函数执行的分支只会在函数第一次调用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,这样任何对原函数的调用就不用再经过执行的分支了.本文将详细介绍惰性 ...
- javascript面向对象系列第四篇——选项卡的实现
前面的话 面向对象的应用并非只是读几本书那么容易,需要有大量的工程实践做基础才能真正理解并学会使用它.本文将用面向对象的技术来制作一个简单的选项卡 图示说明 由图示结果看到,这是一个非常简单的选项卡. ...
- 深入理解javascript作用域系列第五篇——一张图理解执行环境和作用域
× 目录 [1]图示 [2]概念 [3]说明[4]总结 前面的话 对于执行环境(execution context)和作用域(scope)并不容易区分,甚至很多人认为它们就是一回事,只是高程和犀牛书关 ...
- 深入理解javascript作用域系列第五篇
前面的话 对于执行环境(execution context)和作用域(scope)并不容易区分,甚至很多人认为它们就是一回事,只是高程和犀牛书关于作用域的两种不同翻译而已.但实际上,它们并不相同,却相 ...
- 深入理解javascript对象系列第三篇——神秘的属性描述符
× 目录 [1]类型 [2]方法 [3]详述[4]状态 前面的话 对于操作系统中的文件,我们可以驾轻就熟将其设置为只读.隐藏.系统文件或普通文件.于对象来说,属性描述符提供类似的功能,用来描述对象的值 ...
随机推荐
- 简述TCP连接的建立与释放(三次握手、四次挥手)
在介绍TCP连接的建立与释放之前,先回顾一下相关知识. TCP是面向连接的运输层协议,它提供可靠交付的.全双工的.面向字节流的点对点服务.HTTP协议便是基于TCP协议实现的.(虽然作为应用层协议,H ...
- linux菜鸟日记(5)
iptables详细语法及配置: SNAT:源地址转换DNAT:目标地址转换PNAT:端口地址转换 ----------------------------------iptables规则链 路由以后 ...
- 【异常】INFO: TopologyManager: EndpointListener changed ...
5月份做云部署,在调试CSS系统时,出现启动系统时,卡死情况,后台日志如下: May 03, 2016 2:34:52 AM org.apache.cxf.dosgi.topologymanager. ...
- windows消息机制详解(转载)
消息,就是指Windows发出的一个通知,告诉应用程序某个事情发生了.例如,单击鼠标.改变窗口尺寸.按下键盘上的一个键都会使Windows发送一个消息给应用程序.消息本身是作为一个记录传递给应用程序的 ...
- IDEA+Tomcat+JRebel热部署
在完成idea工程简单应用后,接下来实现热部署. 简单应用地址:http://wibiline.iteye.com/admin/blogs/2072454 一.安装JRebel插件 1. 在线安装 F ...
- HDU 3584 Cube (三维 树状数组)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3584 Cube Problem Description Given an N*N*N cube A, ...
- UITextView 点击添加文字 光标处于最后方
#import "ViewController.h" @interface ViewController ()<UITextViewDelegate> @end @im ...
- SEO网站内链匹配工具
最近在弄一个网站,想体验一下SEO方面的工作. 虽然自己是从事.NET方面工作的,但时间有限,所以用了DEDECMS作为网站的程序. 而SEO里面最重要的一项就是内链.但DEDECMS没有直接的内链匹 ...
- java-PreparedStatement的用法
转自:http://www.cnblogs.com/raymond19840709/archive/2008/05/12/1192948.html PreparedStatement的用法 jdbc( ...
- CF2.E
E. Comments time limit per test 2 seconds memory limit per test 256 megabytes input standard input o ...