[JS] 모던 Javascript Deep Dive 26장 - ES6 함수의 추가 기능
업데이트:
[01] 함수의 구분
🎯 ES6 이전
모든 함수는 일반함수로서 호출할 수 있고, 생성자 함수로서 호출할 수도 있다.
Callable + constructor
🎯 ES6 이후
화살표 함수의 등장으로 non-constructor 특성을 지니는 함수가 생겨남.
[02] 메서드
🎯 ES6 이전
메서드에 대한 명확한 정의가 없다. 객체에 바인딩된 함수를 뜻하곤 했다.
🎯 ES6 이후
메서드 축약 표현으로 정의된 함수만을 의미한다.
메서드는 인스턴스를 생성할 수 없는 non-constructor이다.
super 기능을 추가하고 의미적으로 맞지 않는 기능인 constructor을 제거했다.
메서드에서 super 을 사용하는 것은 어떻게 하는걸까? 코드를 통해 보겠다.
const base = {
name: 'Minhye',
sayHi(){
return `Hi! ${this.name}`;
}
};
const derived = {
__proto__: base,
sayHi(){
return `${super.sayHi()}. how are you doing?`;
}
};
console.log(derived.sayHi());
proto 접근자 프로퍼티를 이용하여 base를 derived
객체의 프로토타입으로 지정해주고 메서드 오버라이딩을 하면 base의 프로퍼티를 잘 상속받은 것을 볼 수 있다.
[03] 화살표 함수
정의
📌 화살표 함수는 함수 표현식으로 정의해야 한다.
const minhye= (name, age) => console.log(name, age);
minhye('kang',25); // kang 25
매개변수 선언
- 매개변수가 여러 개일 경우 소괄호 안에 매개변수를 선언
- 매개변수가 한 개인 경우 소괄호 생략 가능
- 매개변수가 없는 경우 소괄호 생략 불가
const arrow = (x,y) => {...};
const arrow2 = x => {...};
const arrow3 = () => {...};
함수 몸체 정의
- 함수 몸체가 하나의 문이면 중괄호를 생략 가능하다. 여러 개의 문이면 중괄호를 생략할 수는 없다.
- 함수 몸체 내부의 문이 표현식인 문(값)이면 암묵적으로 반환된다. 단, 표현식이 아닌 문이라면 중괄호를 꼭 포함해주어야 한다.
const square = x => x ** 2;
square(5); // 25'
const square = x => { return x ** 2};
// x ** 2 가 표현식인 문이기 때문에 암묵적으로 값이 반환되었다.
const arrow = () => { return
- 객체를 반환할 때는 소괄호로 객체 리터럴을 감싸주어야 한다.
const create = (id, content) => ({ id, content });
create(1, 'JavaScript'); // { id: 1, content: 'JavaScript'}
화살표 함수의 this
일반 함수에서 this는 함수가 어떻게 호출되는지에 따라 this 바인딩이 달라진다고 배웠었다.
하지만 화살표 함수에서의 this는 다르다 !
📌 화살표 함수의 this는 선언할 때 바인딩할 객체가 정적으로 결정된다.
동적 스코프가 아닌 렉시컬 스코프와 유사하므로 Lexical this라고 하기도 한다.
콜백 함수 내에서 this 바인딩이 원하는 대로 이루어지지 않는 경우, 화살표 함수를 이용하여 문제를 해결할 수도 있다. (이외에도 bind 메서드 활용, map 인수로 this 전달, that 변수에 this 회피 등의 방법이 있다.)
class Prefixer{
constructor(prefix){
this.prefix = prefix;
}
add(arr){
return arr.map(function(item){
return this.prefix + item; // 메서드로 호출하면 this 바인딩이 호출한 객체가 된다.
// => TypeError: Cannot read property 'prefix' of undefined
});
}
}
const prefixer = new Prefixer('-webkit-');
console.log(prefixer.add(['transition', 'user-select']);
⬇ 화살표 함수로 문제 해결한 코드
class Prefixer{
constructor(prefix){
this.prefix = prefix;
}
add(arr){
return arr.map(item => this.prefix + item); // 화살표 함수의 this는 정의된 곳에서 바인딩된다.
}
}
const prefixer = new Prefixer('-webkit-');
console.log(prefixer.add(['transition', 'user-select']); // ['-webkit-transition', '-webkit-user-select']
콜백 함수로 사용하기 편리하여 화살표 함수가 자주 사용된다.
✍ 화살표 함수에서는 스코프 체인 상에서 가장 가까운 상위 함수 중에서 화살표 함수가 아닌 함수의 this를 참조한다.
화살표 함수의 super
화살표 함수는 함수 자체의 super 바인딩을 갖지 않는다.
📌 화살표 함수 내부에서 super을 참조하면 상위 스코프의 super를 참조한다.
화살표 함수를 사용하면 안되는 경우
- 메소드를 정의하는 것
- 프로토타입에 화살표 함수 메서드를 할당하는 것
- 생성자 함수로 사용하는 것
[04] Rest 파라미터
Rest 파라미터는 말 그대로 나머지 매개변수이다 !
사용법
function foo(...rest){
console.log(...rest);
}
foo(1,2,3,4,5); // [1,2,3,4,5]
매개변수 앞에 … 을 붙여서 사용하면 된다. 매개변수 이름은 꼭 rest가 아니어도 된다.
그리고 여러 매개변수가 있을 때 rest 파라미터는 반드시 마지막이어야 한다.
Rest 파라미터와 arguments 객체
앞에서 arguments 객체로 인수를 전달받는 것을 배운적이 있었다. 그런데 arguments는 유사배열이므로 배열 메서드를 사용할 수는 없다는 단점이 있다.
Rest 파라미터를 사용하면 인수 목록들을 배열로 직접 전달받을 수 있고 배열 메서드 사용도 가능하다 !
그리고 ES6부터 등장한 화살표 함수는 arguments 객체를 갖지 않는다.
화살표 함수에서는 반드시 Rest 파라미터를 사용해야 한다.
[05] 매개변수 기본값
이전에 함수를 호출할 때 매개변수의 개수보다 인수의 개수가 적거나 많은 경우에도 에러가 발생하지 않는다고 배웠다. 그래서 인수가 전달되지 않을 때 의도치 않은 결과가 나올 수도 있었다.
이러한 부작용을 방지하기 위해 ES6에서는 “매개변수 기본값”이라는 것이 도입되었다.
function sum(x = 0, y = 0){ // 매개변수 기본값 (x=0, y=0)
return x+y;
}
console.log(sum(3,6)); // 9
console.log(sum(3)); //3
이제부터는 인수가 매개변수보다 적게 전달되어도 기본값 0이 설정되어 있기 때문에 NaN이 출력되는 부작용을 방지할 수 있다.
맺음말
항상 화살표 함수 문법이 익숙치 않았는데 이번 챕터에서 화살표 함수에 대해 자세히 다뤄서 속이 다 시원했다 ! ES6 이전 이후로 달라진 것들을 면접에서 자주 물어본다고 하니 이 파트는 자주 봐서 익혀두어야겠다.
댓글남기기