默认值和解构数组
你可以将默认函数参数和解构结合到一起, 创建非常强大的函数!
function createGrid([width = 5, height = 5]) {
return `Generates a ${width} x ${height} grid`;
}
createGrid([]); // Generates a 5 x 5 grid
createGrid([2]); // Generates a 2 x 5 grid
createGrid([2, 3]); // Generates a 2 x 3 grid
createGrid([undefined, 3]); // Generates a 5 x 3 grid
Returns:
Generates a 5 x 5 grid
Generates a 2 x 5 grid
Generates a 2 x 3 grid
Generates a 5 x 3 grid
createGrid() 函数预期传入的是数组。它通过解构将数组中的第一项设为 width,第二项设为 height。如果数组为空,或者只有一项,那么就会使用默认参数,并将缺失的参数设为默认值 5。
但是存在一个问题,下面的代码将不可行:
createGrid(); // throws an error
Uncaught TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
出现错误,因为 createGrid() 预期传入的是数组,然后对其进行解构。因为函数被调用时没有传入数组,所以出现问题。但是,我们可以使用默认的函数参数!
function createGrid([width = 5, height = 5] = []) {
return `Generating a grid of ${width} by ${height}`;
}
看到函数参数中的新 = [] 了吗?如果 createGrid() 在被调用时没有任何参数,它将使用这个默认的空数组。因为数组是空的,因此没有任何内容可以解构为 width 和 height,因此将应用它们的默认值!通过添加 = [] 为整个参数设定一个默认值,下面的代码将可行:
createGrid(); // Generates a 5 x 5 grid
Returns: Generates a 5 x 5 grid
看看下面的代码:
function houseDescriptor([houseColor = 'green', shutterColors = ['red']]) {
return `I have a ${houseColor} house with ${shutterColors.join(' and ')} shutters`;
}
下面的哪些选项可以正常运行,不会出现错误?
1.houseDescriptor('red', ['white', 'gray', 'pink']);
2.houseDescriptor(['green', ['white', 'gray', 'pink']]);
3.houseDescriptor(['blue', 'purple']);
4.houseDescriptor(['green']);//答案为2和4
#####默认值和解构对象
就像使用数组默认值解构数组一样,函数可以让对象成为一个默认参数,并使用对象解构:
function createSundae({scoops = 1, toppings = ['Hot Fudge']}) {
const scoopText = scoops === 1 ? 'scoop' : 'scoops';
return `Your sundae has ${scoops} ${scoopText} with ${toppings.join(' and ')} toppings.`;
}
createSundae({}); // Your sundae has 1 scoop with Hot Fudge toppings.
createSundae({scoops: 2}); // Your sundae has 2 scoops with Hot Fudge toppings.
createSundae({scoops: 2, toppings: ['Sprinkles']}); // Your sundae has 2 scoops with Sprinkles toppings.
createSundae({toppings: ['Cookie Dough']}); // Your sundae has 1 scoop with Cookie Dough toppings.
Returns:
Your sundae has 1 scoop with Hot Fudge toppings.
Your sundae has 2 scoops with Hot Fudge toppings.
Your sundae has 2 scoops with Sprinkles toppings.
Your sundae has 1 scoop with Cookie Dough toppings.
就像上面的数组示例,如果尝试调用函数时不传入参数,将不可行:
createSundae(); // throws an error
Uncaught TypeError: Cannot match against 'undefined' or 'null'.
我们可以通过向函数提供默认对象来防止出现此问题:
function createSundae({scoops = 1, toppings = ['Hot Fudge']} = {}) {
const scoopText = scoops === 1 ? 'scoop' : 'scoops';
return `Your sundae has ${scoops} ${scoopText} with ${toppings.join(' and ')} toppings.`;
}
通过添加空对象作为默认参数,以防未提供参数,现在调用函数时没有任何参数将可行。
createSundae(); // Your sundae has 1 scoop with Hot Fudge toppings.
Returns: Your sundae has 1 scoop with Hot Fudge toppings.
习题 2/2
看看下面的代码:
function houseDescriptor({houseColor = 'green', shutterColors = ['red']} = {}) {
return `I have a ${houseColor} house with ${shutterColors.join(' and ')} shutters`;
}
下面的哪些选项可以正常运行,不会出现错误?
1.houseDescriptor({houseColor: 'red', shutterColors: ['white', 'gray', 'pink']});
2.houseDescriptor({houseColor: 'red'});
3.houseDescriptor();
4.houseDescriptor({shutterColors: ['orange', 'blue']});
5.houseDescriptor({});
//所有函数都能运行
数组默认值与对象默认值
默认函数参数只是个简单的添加内容,但是却带来很多便利!与数组默认值相比,对象默认值具备的一个优势是能够处理跳过的选项。看看下面的代码:
function createSundae({scoops = 1, toppings = ['Hot Fudge']} = {}) { … }
在 createSundae() 函数使用对象默认值进行解构时,如果你想使用 scoops 的默认值,但是更改 toppings,那么只需使用 toppings 传入一个对象:
createSundae({toppings: ['Hot Fudge', 'Sprinkles', 'Caramel']});
将上述示例与使用数组默认值进行解构的同一函数相对比。
function createSundae([scoops = 1, toppings = ['Hot Fudge']] = []) { … }
对于这个函数,如果想使用 scoops 的默认数量,但是更改 toppings,则必须以这种奇怪的方式调用你的函数:
createSundae([undefined, toppings: ['Hot Fudge', 'Sprinkles', 'Caramel']]);
因为数组是基于位置的,我们需要传入 undefined 以跳过第一个参数(并使用默认值)来到达第二个参数。
除非你有很充足的理由来使用数组默认值进行数组解构,否则建议使用对象默认值进行对象解构!