资讯专栏INFORMATION COLUMN

ES6指北【4】——ES6的函数参数处理,超乎你想象

Pandaaa / 1325人阅读

摘要:参数搭配的变量是一个数组,该变量将多余的参数放入数组中。从上面的概念中,我们至少可以知道如下三个信息语法变量。

一、函数的默认参数值 1. ES6之前,我们如何实现函数默认参数 1.1 方式一:使用逻辑运算符【||】
function test(x) {
  x = x || "默认值" // 使用||设置默认值
  console.log(x) 
}

test() // "默认值"

但这样做有个非常明显的缺陷
如果x的值为null/+0或-0/NaN/""/false中的一个,x都会被设置为默认值,但我们的本意是在不传值的时候才设置为默认值

因此有了第二种处理方式

1.2 方式二:对参数是否为undefined进行判断
ES5其实本来就有函数默认参数,只不过这个默认参数只能是undefined,无法设置
function test(x) {
  console.log(x)
}

test() // undefined
所以我们只要对传入的值是否为undefined进行判断就可以实现自由设置默认参数了
function test(x) {
  if(!(Object.prototype.toString.call(x) === "[object Undefined]")) {
    console.log("默认值")
  } else {
    console.log(x) 
  }

}

test() // "默认值"
2. ES6实现函数默认参数 2.1 基本用法
其实非常简单,直接在参数后面加个 = 号就行啦,看栗子吧
function test(x = "默认值") {
  console.log(x) 
}

test() // "默认值"
如果要给多个参数赋值,就像下面这样写
function test(x = "默认值1",y = "默认值2") {
  console.log(x,y) 
}

test() // 默认值1 默认值2
但这本质上其实还是对undefined做判断,是1.2小节的语法糖
function f(x = 1) {
    console.log(x)
}
f(undefined) // 1
2.2 参数默认值的惰性求值
参数默认值是不记录值的,每次都会重新计算参数默认表达式的值
// 阮一峰老师 ES6深入浅出 的例子
let x = 99;
function foo(p = x + 1) {
  console.log(p);
}

foo() // 100

x = 100;
foo() // 101 而不是 100
// mdn的例子
function append(value, array = []) {
  array.push(value);
  return array;
}

append(1); //[1]
append(2); //[2] 而不是 [1, 2]
有同学一定会有疑问,这不是废话吗?其实不然,比如Python的参数默认值不一定是惰性求值,比如下面这个例子
>>> def f1(data=[]):
...     data.append(1)
...     return data
...
>>> f1()
[1]
>>> f1()
[1, 1]
>>> f1()
[1, 1, 1]
二、剩余参数
函数剩余参数的英文为 —— Functions Rest Parameters,一般我们剩余参数为rest参数
1. 基本概念
注:概念摘自阮一峰老师的《ECMAScript 6 入门》
ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

从上面的概念中,我们至少可以知道如下三个信息

语法——...+变量。这个变量的数据类型是数组,用来存放多余的参数

作用——用于获取函数的多余参数

语法糖——rest参数一定是arguments对象的语法糖

1.1 基本用法

首先我们要搞清楚什么是多余参数

function sum(x, y) {
  return x + y
}

sum(1, 2, "多余1", "多余2", "多余3") // 3

从上面的例子我们可以看到,sum函数接受两个参数的传递,但是用户传递了五个参数,后面的三个参数即使传递也是无法被sum函数使用,显得有些多余

这里的多余并不是无用的意思,而是相对于被使用到了的参数显得多余而已

那么,如果我们也想对这些多余参数进行处理的话就需要使用rest参数

// 用rest参数改写之后
function sum(x, y, ...paraArr) {
  console.log(paraArr)
  return x + y
}

sum(1, 2, "多余1", "多余2", "多余3") 
// ["多余1", "多余2", "多余3"] 3 
1.2 什么时候我们会用到rest参数?

既然rest参数是arguments的语法糖,那么我们只要搞清楚以往arguments的应用场景是什么,那么自然就懂得如何使用rest参数了。

下面看一个使用arguments的例子

// 创建一个sum函数,实现如下功能
// sum() // 0
// sum(1) // 1
// sum(2,10,2) // 14
// sum(0,0,200,1) // 201
// sum(1,10,3,2,100) // 116

function sum() {
  let total = 0
  for (let i = 0; i < arguments.length; i++) {
      total += arguments[i]
  }
  return total
}

从上面的例子我们可以发现其最大的特点是参数个数不确定,所以如果遇到函数参数个数不确定的情况,就要优先考虑使用rest参数,而且由于rest参数真数组,你用起来会比arguments舒服太多
下面是用rest参数进行改写

// 创建一个sum函数,实现如下功能
// sum() // 0
// sum(1) // 1
// sum(2,10,2) // 14
// sum(0,0,200,1) // 201
// sum(1,10,3,2,100) // 116

function sum(...paraArr) {
  let total = 0
  paraArr.forEach(e => total += e)
  return total
}
2. 拓展:把arguments转换为真数组的三种方式
arguments因为能获取到所有参数所以还是有它的不可替代性的,但是其伪数组的特性实在有点恶心,下面教大家三种方法转换,第一种是ES5的方法,剩下两种是ES6的方法
function sum() {
  let arr1 = Array.prototype.slice.call(arguments)
  let arr2 = Array.from(arguments)
  let arr3 = [...arguments] // 这个是展开语法【spread syntax】 我会在ES6指北的下一章讲解,敬请关注~~
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96923.html

相关文章

  • ES6指北【6】——详谈解构赋值【附赠练习题】

    摘要:指北详谈解构赋值附赠练习题一何谓解构赋值基本概念首先我们看一下给的定义解构赋值语法是一个表达式,这使得可以将值从数组或属性从对象提取到不同的变量中从定义中,我们可以发现解构赋值的作用是对变量进行赋值主要通过两个方面实现这个作用数组将数组中的 ES6指北【6】——详谈解构赋值【附赠练习题】 一、何谓解构赋值? 1. 基本概念 首先我们看一下MDN给的定义 解构赋值语法是一个 Javasc...

    sorra 评论0 收藏0
  • ES6指北【2】—— 箭头函数

    摘要:箭头函数基本语法函数语法具名函数匿名函数三句话第一句话声明第二句话声明匿名函数第三句话把匿名函数赋值给箭头函数语法特点只能做赋值,不能做声明第一种写法完全写法不省略参数个数,不省略函数体花括号参数个数函数体内语句个数第二种写法省略参数括号参 1.箭头函数基本语法 1.1 ES3 函数语法 // 具名函数 function xxx(arg1, arg2) { console.lo...

    DobbyKim 评论0 收藏0
  • ES6指北【5】——展开语法(spread syntax)

    摘要:我们先来看一看的官方定义展开语法可以在函数调用数组构造时将数组表达式或者在语法层面展开还可以在构造字面量对象时将对象表达式按的方式展开。 我们先来看一看MDN的官方定义 展开语法(Spread syntax), 可以在函数调用/数组构造时, 将数组表达式或者string在语法层面展开;还可以在构造字面量对象时, 将对象表达式按key-value的方式展开。(译者注: 字面量一般指 [1...

    ZoomQuiet 评论0 收藏0
  • ES6指北【1】——let、const

    摘要:如何学习的学习顺序以此类推没学好就别想学好边学边用学了就要用变量声明的方式上面两个是的语法,下面两个是的语法块级作用域看会声明一个全局变量吗显然当声明了全局变量后,是无法再声明全局变量的,只能对其赋值结论含义不明的问题下面的代码不会执 1.如何学习ES6 1.1 js的学习顺序 ES5 -> ES6 -> ES7 -> ES8 以此类推 ES5没学好就别想学好ES6 1.2 边学边用 ...

    张春雷 评论0 收藏0
  • ES6指北【1】——let、const

    摘要:如何学习的学习顺序以此类推没学好就别想学好边学边用学了就要用变量声明的方式上面两个是的语法,下面两个是的语法块级作用域看会声明一个全局变量吗显然当声明了全局变量后,是无法再声明全局变量的,只能对其赋值结论含义不明的问题下面的代码不会执 1.如何学习ES6 1.1 js的学习顺序 ES5 -> ES6 -> ES7 -> ES8 以此类推 ES5没学好就别想学好ES6 1.2 边学边用 ...

    tain335 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<