Modern JavaScript와 Default parameters
1. 모던 자바스크립트란?
ECMAScript는 자바스크립트라는 프로그래밍 언어의 표준이라고 이해할 수 있습니다.
ECMA International(국제 표준화 기구)에서 자바스크립트를 사용할 때 준수해야 하는 규칙이나 세부 사항들을 ECAM-262 이름을 가진 문서로 관리를 합니다.
ECMAScript는 1997년에 처음 등장해서 새로운 내용들이 추가될 때마다 ES1, ES2처럼 불렀습니다. 그리고 여섯 번째 버전이 등장한 2015년부터는 1년마다 새로 표준을 출시하기로 결정이 되면서 ES6라는 용어를 그대로 사용하면서도 ECMAScript의 공식적인 버전 명칭은 연호를 붙여서 ES2015, ES2016로 부르기도 합니다.
결국 ECMAScript의 최신 버전이 등장하더라도 개발할 때 최신 버전을 꼭 적용하는 것이 아니라 보편적으로 사용되는 브라우저들이 지원하는 범위 내에서 ECMAScript의 버전을 준수하는 모습이 일반화 되었습니다.
이렇게 변화하는 시대와 상황에 맞춰서 현재 사용하기 적합한 범위 내에서 최신 버전의 표준을 준수하는 자바스크립트를 Modern JavaScript라고 부르게 되었습니다.
2. Default parameters
기본 함수 매개변수는 값이 전달되지 않거나 'undefined'가 전달되었을 때 작성된 매개변수를 기본값으로 초기화할 수 있게 해줍니다.
function greeting(name = 'Joy', interest = 'Javascript') {
console.log(`Hi! My name is ${name}!`);
console.log(`I like ${interest}!`);
}
greeting(undefined, 'Golang'); // Hi! My name is Joy!
// I like Golang!
greeting(null, 'Golang'); // Hi! My name is null!
// I like Golang!
간혹 'null' 값과 'undefined' 를 혼동해서 'null' 값을 전달하더라도 기본값이 사용될 거라 오해할 수도 있는데, 함수를 호출할 때 인수(Argument)로 'null' 값을 사용하게 되면 해당 매개변수(Parameter)는 'null' 값을 그대로 전달받게 됩니다.
JavaScript 기본 매개변수(Parameter) 내용을 총 5가지로 분류하였습니다.
2-1. Passing undefined vs other falsy values
function test(num = 1) {
console.log(typeof num);
}
test(); // 'number' (num is set to 1)
test(undefined); // 'number' (num is set to 1 too)
// test with other falsy values:
test(""); // 'string' (num is set to '')
test(null); // 'object' (num is set to null)
이 예제에서 두 번째 호출 시, 첫 번째 인수가 명시적으로 'undefined'로 설정된 경우(단, 'null' 또는 'falsy' 값은 제외), 'num' 인수의 값은 여전히 기본값으로 설정됩니다.
2-2. Evaluated at call time
function append(value, array = []) {
array.push(value);
return array;
}
append(1); // [1]
append(2); // [2], not [1, 2]
기본 argument는 호출 시 평가됩니다. 예를 들어, Python과 달리 함수가 호출될 때마다 새로운 객체가 생성됩니다.
이것은 함수와 변수에도 적용됩니다.
function callSomething(thing = something()) {
return thing;
}
let numberOfTimesCalled = 0;
function something() {
numberOfTimesCalled += 1;
return numberOfTimesCalled;
}
callSomething(); // 1
callSomething(); // 2
'thing'은 'callSomething' 함수의 매개변수(Parameter)로, 매개변수가 제공되지 않은 채로 함수 'something'이 호출될 때 마다 값이 증가합니다.
2-3. Earlier parameters are available to later defult parameters
function greet(name, greeting, message = `${greeting} ${name}`) {
return [name, greeting, message];
}
greet("David", "Hi"); // ["David", "Hi", "Hi David"]
greet("David", "Hi", "Happy Birthday!"); // ["David", "Hi", "Happy Birthday!"]
'greet' 함수에 정의된 첫 번째, 두 번째 매개변수는 이후 기본 매개변수에서 사용할 수 있습니다.
2-4. Destructured parameter with default value assignment
디스트럭처링 할당 문법을 사용하여 함수에 아무것도 전달하지 않고 해당 값을 미리 채울 수 있습니다.
function preFilledArray([x = 1, y = 2] = []) {
return x + y;
}
preFilledArray(); // 3
preFilledArray([]); // 3
preFilledArray([2]); // 4
preFilledArray([2, 3]); // 5
// Works the same for objects:
function preFilledObject({ z = 3 } = {}) {
return z;
}
preFilledObject(); // 3
preFilledObject({}); // 3
preFilledObject({ z: 2 }); // 2
'preFilledArray' 함수는 parameter로 배열을 받습니다. 기본값으로 빈 배열('[]')을 설정합니다.
'preFilledObject' 함수는 parameter로 객체를 받습니다. 기본값으로 빈 객체('{}')를 설정합니다.
2-5. Error or not error?
console.log(preFilledArray(null)); //Falsy 값
console.log(preFilledArray(NaN)); //Falsy 값
console.log(preFilledArray(0)); //Falsy 값
console.log(preFilledArray('')); //Falsy 값
console.log(preFilledArray(false)); //Falsy 값
console.log(preFilledArray([])); //Truthy 값
'preFilledArray' 함수에 'null', 'NaN', '0', 빈 문자열(' '), 'false' 또는 빈 배열([ ])이 인수(argument)로 전달될 때, 어떤 경우에 Error가 발생할까요?
TypeError: boolean false is not iterable (cannot read property Symbol(Symbol.iterator))
빈 문자열(' ') 또는 빈 배열([ ])일 때는 default value이 출력되었지만, 그외의 값들은 오류가 발생했습니다.
console.log(preFilledObject(null)); //Falsy 값
console.log(preFilledObject(NaN)); //Falsy 값
console.log(preFilledObject(0)); //Falsy 값
console.log(preFilledObject('')); //Falsy 값
console.log(preFilledObject(false)); //Falsy 값
console.log(preFilledObject([])); //Truthy 값
'preFilledObject' 함수는 어떻게 될까요?
TypeError: Cannot read properties of null (reading 'z')
마찬가지로, 문자열과 배열 이외의 값에서는 오류가 발생했습니다.
문자열과 배열은 왜 오류가 없을까요?
이터러블(Interable)이란 자료를 반복 가능한 객체를 말하는데, 객체 내의 요소들을 한 번에 하나씩 순회할 수 있는 구조입니다.
배열(Array)은 대표적인 이터러블입니다. 그리고, 문자열(String), Map, Set 등은 모두 내장된 이터러블입니다.
따라서, 배열과 문자열은 이터러블이기 때문에 *디스트럭처링할 수가 있고, error 없이 default value로 출력됩니다.
*디스트럭처링(Destructuring)은 구조화된 배열 또는 객체를 Destructuring(비구조화, 파괴)하여 개별적인 변수에 할당하는 것