ES6-一个关于函数解构赋值默认值的有趣案例
在说这个小案例前,先简单的梳理一下ES6的解构和默认值赋值
PS: 已经了解的同志的同志可以直接看小栗子
1. ES6的解构
ES6中引入了解构赋值的操作,其作用是:将值从数组Array
或属性从对象Object
提取到不同的变量中
即分为两种情况:从数组
Array
中解构,以及从对象Object
中解构
①.从数组中解构
const [a, b] = [1, 2]
//a = 1, b = 2
当然这些是基本的数组解构赋值,你还可以用逗号,
进行跨值解构,用扩展运算符...
进行多余项的解构等等
②.从对象种结构
const {a, b} = {a: 1, a: 2}
//a = 1, b = 2
这也是基本的对象结构赋值,不过在这里提一下,你仍然可以用扩展运算符...
进行多余项的解构:
const {a, ...b} = {a: 1, b: 2, c: 3, d: 4}
//a = 1
//b = {b: 2, c: 3, d: 4}
③. 其他类型
当解构其他类型时,也是先将其他类型值转换为Array
或者Object
const [a, b, c] = 'hello'
// a = 'h', b = 'e', c = 'l'
const {toString: a} = true
toString === Boolean.prototype.toString // true
2. ES6的函数默认参数
① 定义
函数默认参数允许在没有值或undefined
被传入时使用默认形参。
栗子:
function foo (a = 1, b = 2) {
console.log(a, b)
}
foo ()// 1 2
Note: 形参默认是undefiend, 也就是说,在没有默认值时,a = undefiend, b = undefined;不过上面这个例子是没有值被传入的情况
undefiend
被传入的情况如下:
function foo (a = 1, b = 2) {
console.log(a, b)
}
foo (undefined, window.valueIsNotDefined)// 1 2
② 默认值不是只有函数参数才能用
还是直接举个例子:
var {a = 1, b = 2} = {}
// a = 1, b = 2
var {a = 1, b = 2} = {a: 'hello'}
// a = 'hello', b = 2
其实解构赋值也是可以赋值默认值的;由此可见:
函数参数默认值的本质,还是解构赋值
3. 一个有趣的小栗子
说了那么多废话,终于要说到这个小栗子了。
Step 1
这是一种超常见的情况,有的时候,当我们定义函数参数的时候,可以去解构当前的参数
比如:
function foo ({ a, b }) {
console.log(a, b)
}
foo({ a: 1, b: 2 })// 1 2
Note: 可以看成做了以下操作:
const { a, b } = { a: 1, b: 2 };
console.log(a, b)
Step 2
更多的时候,我们不会满足于此,我们想要一个默认值
function foo ({a = 1, b = 2}) {
console.log(a, b)
}
foo({})// 1 2
Note: 可以看成做了以下操作:
const { a = 1, b = 2 } = {};
console.log(a, b)
问题 1
然而,我们实际使用时,不会用foo({})
这种写法来表示参数缺省,我们大多数人采用foo()
这种显而易见的写法,由此问题来了
function foo ({a = 1, b = 2}) {
console.log(a, b)
}
foo()
Uncaught TypeError: Cannot destructure property `a` of 'undefined' or 'null'.
at foo (<anonymous>:1:14)
at <anonymous>:4:1
通过换一种写法,不难发现错误原因:
const {a = 1, b = 2} = undefined // Error
解决方法:
其实,function foo ({a = 1, b = 2}) {}
是对第一个参数的解构,那我们完全按照文章前面函数默认参数定义的那样,在参数为undefined
或没有传入
的时候,预先定义:
function foo ({a, b} = {a: 1, b: 2}) {
console.log(a, b)
}
foo()// 1 2
分析:可以看做以下写法
function foo (temp = {a: 1, b: 2}) {
var {a, b} = temp
console.log(a, b)
}
foo()// 1 2
问题 2
上面这种方法看似解决了问题,但当我们回过头来,重新运行foo({})
,却出现了错误:
function foo ({a, b} = {a: 1, b: 2}) {
console.log(a, b)
}
foo({}) // undefined undefined
经历了前面情景的分析后,现在不难发现:此时的函数参数传入了一个有效值,所以temp
不会去采纳默认值,而是去采纳有效的传入值{}
; 而var { a, b } = {}
的解构,自然而然会让a
和b
变为undefined
解决方法:
我们很自然的想到:var { a = 1, b = 2 } = {}
的形式,来解决这种情况,所以,原函数写作:
function foo ({ a = 1, b = 2 } = {}) {
console.log(a, b)
}
foo()// 1 2
foo({})//1 2