... 점(dot) 세개를 연달아 사용하는 문법
allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.
MDN
* Iterable이란? Array, String, Map, Set, HTMLCollection, NodeList 등 이터러블 형식에 맞는 순회 가능한 자료구조
It is commonly used when you want to add a new item to a local data store, or display all stored items plus a new addition.(as many times as you like)
console.log(...[10, 20, 30]); // console.log(10, 20, 30)으로 변환되어 실행됨
// apply()
function myFunction(x, y, z) { }
let args = [0, 1, 2];
myFunction.apply(null, args);
// With spread syntax
function myFunction(x, y, z) { }
let args = [0, 1, 2];
myFunction(...args);
// the spread syntax can be used multiple times.
function myFunction(v, w, x, y, z) { }
let args = [0, 1];
myFunction(-1, ...args, 2, ...[3]);
When calling a constructor with new it's not possible to directly use an array and apply(). However, an array can be easily used with new thanks to spread syntax
let dateFields = [1970, 0, 1]; // 1 Jan 1970
let d = new Date(...dateFields);
Just like spread for argument lists, ... can be used anywhere in the array literal, and may be used more than once.
let arr = [1, 2, 3];
let arr2 = [...arr]; // like arr.slice()
arr2.push(4);
// arr2 becomes [1, 2, 3, 4]
// arr remains unaffected
배열을 복사할 때 참조 주소값이 아니라, 값만 복사하기 때문에! 별도의 배열로 복사해서 사용할 수 있다.
arr[0] = 100; // change an element of the arr
arr // [100 , 1, 2, 3]
arr2 // [1, 2, 3, 4]
** 주의: deep cloning 관련 (Object.assign())
// Array.prototype.concat()
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1 = arr1.concat(arr2);
//spread syntax
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2]; // arr1 is now [0, 1, 2, 3, 4, 5]
// Note: Not to use const otherwise, it will give TypeError (invalid assignment)
// Array.prototype.unshift()
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
Array.prototype.unshift.apply(arr1, arr2) // arr1 is now [3, 4, 5, 0, 1, 2]
// spread syntax
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1 = [...arr2, ...arr1]; // arr1 is now [3, 4, 5, 0, 1, 2]
Shallow-cloning (excluding prototype) or merging of objects is now possible using a shorter syntax than Object.assign().
let obj1 = { foo: 'bar', x: 42 };
let obj2 = { foo: 'baz', y: 13 };
let clonedObj = { ...obj1 }; // Object { foo: "bar", x: 42 }
let mergedObj = { ...obj1, ...obj2 }; // Object { foo: "baz", x: 42, y: 13 }
--------------------------------------------------------------------------------
let obj1 = { foo: 'bar', x: 42 };
let obj2 = { foo: 'baz', y: 13 };
const merge = ( ...objects ) => ( { ...objects } );
let mergedObj1 = merge (obj1, obj2); // Object { 0: { foo: 'bar', x: 42 }, 1: { foo: 'baz', y: 13 } }
let mergedObj2 = merge ({}, obj1, obj2); // Object { 0: {}, 1: { foo: 'bar', x: 42 }, 2: { foo: 'baz', y: 13 } }
it spreads an array of arguments into the object literal, due to the rest parameter.
Objects themselves are not iterable, but they become iterable when used in an Array, or with iterating functions such as map(), reduce(), and assign()
let obj = {'key1': 'value1'};
let array = [...obj]; // TypeError: obj is not iterable
function f(a, b, ...theArgs) {
statement
}
foo(...one, ...wrong, ...wrong) /// has to be only one!!!
foo(...wrong, arg2, arg3)
foo(arg1, arg2, ...correct) /// has to be last!!
Rest parameters are real arrays; the arguments object is not.
Rest parameters are Array instances, meaning methods like sort, map, forEach or pop can be applied on it directly;
function myFun(a, b, ...manyMoreArgs) {
console.log("a", a);
console.log("b", b);
console.log("manyMoreArgs", manyMoreArgs);
}
myFun("one", "two", "three", "four", "five", "six");
// 질문: 콘솔은 순서대로 어떻게 찍힐까요?
a one
b two
manyMoreArgs ["three", "four", "five", "six"]<--------An array!!!!!!
-----------------------------------------------------------------------
myFun("one", "two", "three")
// a, "one"
// b, "two"
// manyMoreArgs, ["three"] <-- notice it's an array, even though there's just one value
-----------------------------------------------------------------------
myFun("one", "two")
// a, "one"
// b, "two"
// manyMoreArgs, [] <-- yip, still an array
rest arguments 항상 배열 만듬 : 전달하는 인자가 없으면 빈 배열[]
function fun1(...theArgs) {
console.log(theArgs.length)
}
fun1() // 0 <-------------Since theArgs is an array
fun1(5) // 1
fun1(5, 6, 7) // 3
a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.
Spread 문법을 이용하여 값을 해체한 후, 개별 값을 변수에 새로 할당하는 과정
할당문의 좌변에서 사용하여, 원래 변수에서 어떤 값을 분해해 할당할지 정의합니다.
Basic variable assignment(기본 변수 할당)
var foo = ["one", "two", "three"];
var [one, two, three] = foo;
console.log(one); // "one"
console.log(two); // "two"
console.log(three); // "three"
Assignment separate from declaration(선언에서 분리한 할당)
변수의 선언이 분리되어도 구조 분해를 통해 값을 할당.
var a, b;
[a, b] = [1, 2];
console.log(a); // 1
console.log(b); // 2
Default values(기본값)
변수에 기본값을 할당하면, 분해한 값이 undefined일 때 그 값을 대신 사용합니다.
var a, b;
[a=5, b=7] = [1];
console.log(a); // 1
console.log(b); // 7
Swapping variables(변수 값 교환하기)
하나의 구조 분해 표현식만으로 두 변수의 값을 교환할 수 있습니다.
구조 분해 할당 없이 두 값을 교환하려면 임시 변수가 필요합니다. (일부 로우 레벨 언어에서는 XOR 교체 트릭을 사용할 수 있습니다)
var a = 1;
var b = 3;
[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1
Parsing an array returned from a function(함수가 반환한 배열 분석)
함수는 이전부터 배열을 반환 가능했지만 but 구조 분해를 사용, 반환된 배열에 대한 작업을 더 간결하게 수행
아래 예제에서 f()는 출력으로 배열 [1, 2]을 반환하는데, 하나의 구조 분해만으로 값을 분석할 수 있습니다.
function f() {
return [1, 2];
}
var a, b;
[a, b] = f();
console.log(a); // 1
console.log(b); // 2
Ignoring some returned values(반환 값 무시)
필요하지 않은 반환 값을 무시가능
function f() {
return [1, 2, 3];
}
var [a, , b] = f();
console.log(a); // 1
console.log(b); // 3
**반환 값을 모두 무시할 수도 있습니다.**
[,,] = f();
Assigning the rest of an array to a variable
When destructuring an array, you can unpack and assign the remaining part of it to a variable using the rest pattern
const [a, b,...c] = [1, 2, 3, 4];
console.log(a); // 1
console.log(c); // [3, 4]
Unpacking values from a regular expression match
Basic assignment
const user = {
id: 42,
is_verified: true
};
const {id, is_verified} = user;
console.log(id); // 42
console.log(is_verified); // true
Assignment without declaration
let a, b;
({a, b} = {a: 1, b: 2});
**할당문 둘러싼 ( ... ); 필요** const {a, b} = {a: 1, b:2}와 같다
Assigning to new variable names
A property can be unpacked from an object and assigned to a variable with a different name than the object property.
const o = {p: 42, q: true};
const {p: foo, q: bar} = o;
console.log(foo); // 42
console.log(bar); // true
const {p: foo} = o takes from the object o the property named p and assigns it to a local variable named foo.
Default values
const {a = 10, b = 5} = {a: 3};
console.log(a); // 3
console.log(b); // 5
*Assigning to new variables names and providing default values
const {a: aa = 10, b: bb = 5} = {a: 3};
console.log(aa); // 3
console.log(bb); // 5
Unpacking fields from objects passed as a function parameter
const user = {
id: 42,
displayName: 'jdoe',
fullName: {
firstName: 'John',
lastName: 'Doe'
}
};
function userId({id}) {
return id;
}
function whois({displayName, fullName: {firstName: name}}) {
return `${displayName} is ${name}`;
}
console.log(userId(user)); // 42
console.log(whois(user)); // "jdoe is John"
Rest in Object Destructuring
let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}
a; // 10
b; // 20
rest; // { c: 30, d: 40 }