Arguments Object & Rest Parameters &spread operator

最近在玩 edabit JS 解題,滿喜歡這個平台的,有空就可以玩一下,每天就會有跟 Github commit ㄧ樣的綠點點,目前是我登入的第 9 天,總共解了 50 題 JS,都滿基礎的題目,不過滿適合新手寫的~

https://edabit.com/challenges

今天剛好解到一題,剛好是 Parameters & Arguments 的常見題,想說複習一下:

Parameter 是指函數定義中參數,而 Argument 指的是函數調用時的實際參數。

簡略描述為:Parameter=形參(formal parameter), Argument=實參(actual parameter)。

  • Parameters are variables listed as a part of the function definition.
  • Arguments are values passed to the function when it is invoked.
題目是這樣:
需要完成一個 function:
function numberArgs(str) {
}
得出來的解答需為如下:
numberArgs(“a”, “b”, “c”) ➞ 3
numberArgs(10, 20, 30, 40, 50) ➞ 5
numberArgs(x, y) ➞ 2
numberArgs() ➞ 0

我的解法:

function numberArgs(str) {
 let a = [...str].length;
 return a;
}

The arguments parameter

function argumentVar(parameter1, parameter2, parameter3){
console.log(arguments.length); // 5 is the number of arguments
console.log(arguments[3]); // 4 is the 4th argument
}
argumentVar(1,2,3,4,5);

重要 ES6 寫法: Rest Parameters

function restParam(...restArgs){
console.log(restArgs.length); // 5 is the number of arguments
console.log(restArgs[3]); // 4 is the 4th argument
}
restParam(1,2,3,4,5);

MDN Spread syntax 範例

以前的寫法:
function sum(x, y, z) {

return x + y + z;
}
console.log(sum(1,2,3)); //得到 6
ES6 寫法:
const numbers = [1, 2, 3];
console.log(sum(…numbers));
// expected output: 6
console.log(sum.apply(null, numbers));
// expected output: 6
  • …restArgs 在這裡創造了一個 array restArgs ,裡面有所有的 arguments passed 。* rest parameter 必須要擺在最後,不然會噴 Syntax error : parameter after rest parameter.

其他範例:

function sumAll(...args) { // args is the name for the array
let sum = 0;
for (let arg of args) sum += arg;
return sum;  
}
console.log( sumAll(1) ); // 1
console.log( sumAll(1, 2) ); // 3
console.log( sumAll(1, 2, 3) ); // 6

其他範例:

function showName(firstName, lastName, ...titles) {
  console.log( firstName + ' ' + lastName ); // Julius Caesar

 // the rest go into titles array
 // i.e. titles = ["Consul", "Imperator"]
 console.log( titles[0] ); // Consul
  console.log( titles[1] ); // Imperator
  console.log( titles.length ); // 2
}
showName("Julius", "Caesar", "Consul", "Imperator");

Arguments Object 和 Rest Parameters 的差異:

  • Rest Parameters 是 array ,可以使用 method,如同 forEach and sort
  • arguments object 雖然有length method,但不是真的 array。”But the downside is that although arguments is both array-like and iterable, it’s not an array. It does not support array methods, so we can’t call arguments.map(...) for example.”
  • Rest Parameters contains arguments that have no corresponding parameter while arguments object contains all the arguments passed to the function.
function restParam(parameter1, ...restArgs){
console.log(parameter1); // 1
console.log(restArgs[2]); //4
}
restParam(1,2,3,4,5);

Spread Operator 和 Rest Parameters 的差異:

let arr = [3, 5, 1];

console.log( Math.max(arr) ); // NaN

正確用法:

let arr = [3, 5, 1];

alert( Math.max(...arr) ); // 5 

We also can pass multiple iterables this way:

let arr1 = [1, -2, 3, 4];
let arr2 = [8, 3, -8, 1];

console.log( Math.max(...arr1, ...arr2) ); // 8

We can even combine the spread operator with normal values:

let arr1 = [1, -2, 3, 4];
let arr2 = [8, 3, -8, 1];

alert( Math.max(1, ...arr1, 2, ...arr2, 25) ); // 25

Also, the spread operator can be used to merge arrays:

let arr = [3, 5, 1];
let arr2 = [8, 9, 15];

let merged = [0, ...arr, 2, ...arr2];

console.log(merged); // 0,3,5,1,2,8,9,15 (0, then arr, then 2, then arr2)

Spread operator — turn the string into array

1.[...str]
2.for..of
3.Array.from

let str = "Hello";

console.log( [...str] ); // H,e,l,l,o

*The spread operator internally uses iterators to gather elements, the same way as for..of does.

*So, for a string, for..of returns characters and ...str becomes "H","e","l","l","o". The list of characters is passed to array initializer [...str].

For this particular task we could also use Array.from, because it converts an iterable (like a string) into an array:

let str = "Hello";

// Array.from converts an iterable into an array
alert( Array.from(str) ); // H,e,l,l,o

But there’s a subtle difference between Array.from(obj) and [...obj]:

  • Array.from operates on both array-likes and iterables.
  • The spread operator operates only on iterables.

Summary

When we see "..." in the code, it is either rest parameters or the spread operator.

There’s an easy way to distinguish between them:

  • When ... is at the end of function parameters, it’s “rest parameters” and gathers the rest of the list of arguments into an array.
  • When ... occurs in a function call or alike, it’s called a “spread operator” and expands an array into a list.

Use patterns:

  • Rest parameters are used to create functions that accept any number of arguments.
  • The spread operator is used to pass an array to functions that normally require a list of many arguments.

Create a function to calculate the determinant of a 2 x 2 matrix. The determinant of the following matrix is: ad - bc:

[[a, b], [c, d]]
Example: calcDeterminant([
  [1, 2],
  [3, 4]
]) ➞ -2

calcDeterminant([
  [5, 3],
  [3, 1]
]) ➞ -4

calcDeterminant([
  [1, 1],
  [1, 1]
]) ➞ 0

解法:

function calcDeterminant(matrix) {

var a = (matrix[0][0]* matrix[1][1])-(matrix[0][1]* matrix[1][0]);

return a;

}

Destructuring assignment 可參考