본문 바로가기

Javascript

[Javascript] Argument 와 spread 연산자(...)

Argument

arguments is an Array-like object accessible inside functions that contains the values of the arguments passed to that function. - MDN

 

함수의 인자값이 거기서 거기지 뭐 그리 특별할게 있나 생각할 수 있는데, 다른 프로그래밍 언어 대비, 독특한 특성에 대해 나열해 보겠습니다.

 

1. 항상 옵셔널 합니다.

function SayHi(a,b){
	console.log('Hi ',a,b);
}

SayHi() // Hi undefined undefined

선언 시, 파라미터를 지정해 줘도, 호출 시, 사용여부는 사용자에게 달려있습니다.

단, 호출 시, 인수를 제공하지 않더라도, 선언된 파라미터에 대해 메모리는 할당 됩니다.

SayHi 함수 호출 시, a 와 b 자리에 undefined로 표기되는 것을 보니 호이스팅 된 것을 확인 할 수 있습니다. (대충 메모리 할당 되었다는 의미)

 

2. arguments 예약어로 접근가능

 

function sayHi(a,b,c){
  console.log(arguments)
  console.log(arguments instanceof Array)
  console.log(arguments.pop())
}

sayHi('ham' , 'bacon')

함수 호출 시, 실행 문맥(Execution context)가 생성 되면서, 기본적으로는 3가지(variable environment, 'this', 외부 환경으로의 참조)가 생성되지만, 함수의 경우 arguments가 추가적으로 생성됩니다.

MDN에서 발췌한 설명에 따르면, array-liked objecy, 배열 비스무리한 객체라고 표현합니다. 위에 예시를 실행 시켜 보면 다음과 같은 결과를 얻을 수 있습니다.

 

Array.prototype.length는 지원하는데, Array.prototype.pop는 지원 안하네요!

(length , callee만 지원하는것 같습니다)

 

Spread 연산자

ES6에서 새로 추가된 문법이죠? 개인적으로 React에서, 컨포넌트 정의할 때, 각종 props 넘겨줄 때 많이 사용합니다만, 위의 예시를 한번 spread연산자를 이용해 다시 만들어 봅시다.

function sayHi(...a){
	console.log(a)
}
sayHi('Ham','Bacon') // ['Ham','Bacon']
sayHi('Ham','Bacon' , 'cheese') //['Ham','Bacon' , 'cheese']

arguments예약어와 똑같은 결과지만, arguments와는 다르게 a는 완벽한 array 인스턴스입니다.

function sayHi(...a){
  console.log(arguments instanceof Array) //false
  console.log(a instanceof Array) // true
}

다음과 같이 특정 부분부터 스프레딩도 가능합니다.

function sayHi(a,...b){
  console.log(a) //'ham'
  console.log(b) //['bacon' , 'chees']
}

그럼 어떤 경우에 spreading 가능할까요?

 

해당 변수값이 iterable하면 모두 spreading 가능합니다.

 

iterable에 대해서는 추후 글에 서술하겠지만, 간단히 말해서 iterable protocol을 따르는 모든 값에 대해 가능합니다.

 

대표적인 내장 iterable한 값들로는, string , array 정도가 있을 것 같습니다.

console.log(...'hello') //'h''e''l''l''o'
console.log(...[1,2,3]) // 1 2 3

 

iterable protocol을 따르기만 하면 모두 spreading이 가능하니, 커스텀 iterable한 데이터를 만들면 그 또한 spreading이 가능하겠습니다.

const iterableObj = {};
iterableObj[Symbol.iterator] = function* () {
    yield 1;
    yield 4;
    yield 9;
};
console.log(...iterableObj) // [1, 4, 9]
console.log(...{}) // error