본문 바로가기
모던 자바스크립트 튜토리얼

SOPT 자스 스터디 4주차

by 치우치지않는 2023. 5. 14.

나머지 매개변수 ... 과 스프레드 문법으로서의 ...

나머지 매개변수로 ... 을 사용할 경우, 나머지 매개변수는 모두 ...을 붙인 배열에 집어넣으라는 뜻이 된다. 

이때 나머지 매개변수 ... 은 맨 마지막 매개변수로 온다는 것에 주의하자! 

function showName(firstName, lastName, ...titles) {
  alert( firstName + ' ' + lastName ); // Bora Lee

  // 나머지 인수들은 배열 titles의 요소가 됩니다.
  // titles = ["Software Engineer", "Researcher"]
  alert( titles[0] ); // Software Engineer
  alert( titles[1] ); // Researcher
  alert( titles.length ); // 2
}

showName("Bora", "Lee", "Software Engineer", "Researcher");

이것도 귀찮을 정도로 매개변수가 많다면, 유사 배열 객체 arguments 를 이용하면, 인덱스를 이용해 인수에 접근할 수 있다.

function showName() {
  alert( arguments.length );
  alert( arguments[0] );
  alert( arguments[1] );

  // arguments는 이터러블 객체이기 때문에
  // for(let arg of arguments) alert(arg); 를 사용해 인수를 펼칠 수 있습니다.
}

// 2, Bora, Lee가 출력됨
showName("Bora", "Lee");

// 1, Bora, undefined가 출력됨(두 번째 인수는 없음)
showName("Bora");

또 arguments 가 유사 배열 객체 이므로, 이터러블하고 따라서 for of 를 사용함으로써 인수를 펼칠 때 유용하다는 것도 기억해 두자. (map 은 당연하게도 안 된다. arguments 는 어쨋거나 객체이기 때문에)

한 가지 아쉬운 점, argumetns 는 화살표 함수에서는 지원되지 않는다. 

let arr = [3, 5, 1];

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

이 코드는 NaN 을 반환한다. 이유는 max 의 인수로는 배열이 아니라 3,5,1 과 같은 숫자 목록을 받기 때문에 그렇다. 

이럴 때 스프레드로서의 ...을 활용하면 된다. 

let arr = [3, 5, 1];

alert( Math.max(...arr) ); // 5 (스프레드 문법이 배열을 인수 목록으로 바꿔주었습니다.)

이렇게 arr[0] arr[1] arr[2] 로 분해해 준다. 이때 함수의 매개변수로서의 ...과 달리 여러 개의 ... 을 이용해도 괜찮고, 혼합도 괜찮고, 어디에서나 써도 된다.

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

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

스프레드...은 배열을 합칠 때도 유용하다.

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

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

alert(merged); // 0,3,5,1,2,8,9,15 (0, arr, 2, arr2 순서로 합쳐집니다.)

스프레드 ... 이용하여 배열과 객체 복사하기

let arr = [1, 2, 3];
let arrCopy = [...arr]; // 배열을 펼쳐서 각 요소를 분리후, 매개변수 목록으로 만든 다음에
                        // 매개변수 목록을 새로운 배열에 할당함

// 배열 복사본의 요소가 기존 배열 요소와 진짜 같을까요?
alert(JSON.stringify(arr) === JSON.stringify(arrCopy)); // true

// 두 배열은 같을까요?
alert(arr === arrCopy); // false (참조가 다름)

// 참조가 다르므로 기존 배열을 수정해도 복사본은 영향을 받지 않습니다.
arr.push(4);
alert(arr); // 1, 2, 3, 4
alert(arrCopy); // 1, 2, 3
let obj = { a: 1, b: 2, c: 3 };
let objCopy = { ...obj }; // 객체를 펼쳐서 각 요소를 분리후, 매개변수 목록으로 만든 다음에
                          // 매개변수 목록을 새로운 객체에 할당함

// 객체 복사본의 프로퍼티들이 기존 객체의 프로퍼티들과 진짜 같을까요?
alert(JSON.stringify(obj) === JSON.stringify(objCopy)); // true

// 두 객체는 같을까요?
alert(obj === objCopy); // false (참조가 다름)

// 참조가 다르므로 기존 객체를 수정해도 복사본은 영향을 받지 않습니다.
obj.d = 4;
alert(JSON.stringify(obj)); // {"a":1,"b":2,"c":3,"d":4}
alert(JSON.stringify(objCopy)); // {"a":1,"b":2,"c":3}

이처럼, 배열과 객체를 복사할 때, ...은 매우 유용하게 사용될 수 있다.

전역 객체 

전역 객체를 사용하면 어디서나 사용 가능한 변수/함수를 만들 수 있다. 브라우저에서는 전역 객체를 window 라고 하고, node.js 에서는 global 이라고 부른다.

전역객체에 접근할 때는 window. global. 처럼 일반 객체처럼 접근하면 된다. 

name 프로퍼티 (함수는 객체이다. 따라서 프로퍼티를 가진다.)

name 프로퍼티를 사용하면, 함수의 이름을 가져올 수 있다. 

function sayHi() {
  alert("Hi");
}

alert(sayHi.name); // sayHi

let sayHi = function() {
  alert("Hi");
};

alert(sayHi.name); // sayHi (익명 함수이지만 이름이 있네요!)

let user = {

  sayHi() {
    // ...
  },

  sayBye: function() {
    // ...
  }

}

alert(user.sayHi.name); // sayHi
alert(user.sayBye.name); // sayBye

length 프로퍼티

length 프로퍼티는 함수의 매개변수의 개수를 반환한다. 

function f1(a) {}
function f2(a, b) {}
function many(a, b, ...more) {}

alert(f1.length); // 1
alert(f2.length); // 2
alert(many.length); // 2

함수는 객체이므로, 커스텀 프로퍼티를 작성할 수 있다.

function sayHi() {
  alert("Hi");

  // 함수를 몇 번 호출했는지 세봅시다.
  sayHi.counter++;
}
sayHi.counter = 0; // 초깃값

sayHi(); // Hi
sayHi(); // Hi

alert( `호출 횟수: ${sayHi.counter}회` ); // 호출 횟수: 2회

댓글