JavaScript
20210709 JavaSciprt DeepDive 08 : ES6 메서드(축약표현), 화살표 함수, Rest 파라미터, 매개변수 기본값
JavaScript Deep Dive 08
용어 및 중요사항 정리
ES6 함수의 추가 기능
- 자바스크립트에서 ES6 이전 함수는 다양한 방식으로 호출이 가능함 -> 함수의 구분이 없음, 대부분이 프로토타입 객체를 생성함 -> 실수 유발, 성능 저하
- 일반 함수 호출
- 생성자 함수 호출
- 메서드로서 호출
- callble(호출할 수 있는 함수 객체) 이면서 contructor(인스턴스를 생성할 수 있는 함수 객체) 임
함수 구분 | constructor | prototype | super | arguments |
---|---|---|---|---|
일반함수 (함수 선언문, 표현식) |
O | O | X | O |
메서드 | X | X | O | O |
화살표 함수 | X | X | X | X |
ES6 메서드 (메서드 축약 표현)
메서드
:- 과거 : 객체에 바인딩된 함수를 일컫는 의미
- ES6 :
메서드 축약 표현
으로 정의된 함수만 의미- non-consturctor로 인스턴스 생성 X -> 생성자 함수로서 호출 X
- prototype 프로퍼티 X, 프로토타입 생성 X
- 표준 빌트인 객체가 제공하는 프로토타입 메서드, 정적 메서드는 non-contructor 임 (메서드니까)
- ES6 메서드는 자신을 바인딩한 객체를 가리키는 내부 슬롯 [[HomeObject]]를 갖음 -> super 키워드 사용 가능
- 객체 리터럴 방식의 객체의 __proto__ 프로퍼티에 부모를 할당하여 상속 구현이 가능함
- 메서드 정의시 프로퍼티에 익명 함수 표현식을 할당하는 방식은 사용하지 말자
const obj = {
x: 1,
foo() {
return this.x;
}, // ES6 메서드
bar: function () {
return this.x;
}, // 일반 함수
};
console.log(obj.foo()); // 1 (ES6 메서드)
console.log(obj.bar()); // 1 (일반 함수)
new obj.foo(); // Type Error : not a constructor (ES6 메서드)
new obj.bar(); // bar{} (일반 함수)
obj.foo.hasOwnProperty("prototype"); // false (ES6 메서드)
obj.bar.hasOwnProperty("prototype"); // true (일반 함수)
화살표 함수
화살표 함수
:- 함수 선언문으로 정의할 수 없고 함수 표현식으로 정의함 (호출 방식은 기존 함수와 동일)
- 매개변수 :
- 매개 변수가 여러 개인 경우 소괄호 ()안에 매개변수 선언
- 1개인 경우 소괄호 생략 가능, 0개인 경우 소괄호 생략 불가
- 중복된 매개변수 이름 선언 X, Duplicate prameter name X (일반 함수는 가능함)
- 함수 몸체 :
- 표현식인 문 하나로 된 경우만 중괄호 생략 가능 (해당 표현식인 문은 return 값으로 인식)
- 여러개의 문으로 구성되면 중괄호 생략 불가
- 객체 리터럴 반환시 ()소괄호로 묶어주어야 함
- 객체 리터럴의 중괄호 보다, 함수 몸체를 의미하는 중괄호가 우선되어 인식
- 표현식인 문 하나로 된 경우만 중괄호 생략 가능 (해당 표현식인 문은 return 값으로 인식)
- 즉시 실행 함수 사용 가능
- 화살표 함수는 일급객체임 -> 고차함수(HOF)에 인수로 전달 가능
- 콜백함수 정의시 유용
- 인스턴스 생성 불가한 non-constructor 임 -> 생성자 함수로서 호출 X, 프로토타입 생성 X
- 함수 자체 this, arguments, super, new.target 바인딩 X -> 상위 스코프 기준으로 바인딩 O
- 화살표 함수로 기존의 메서드를 만들지 말자, 메서드는 항상 ES6 메서드 축약만 사용하자
화살표 함수의 this
콜백함수 내부의 this 문제
- 콜백함수가 함수 표현식으로 작성된 경우, 콜백함수는 일반 함수로 호출 됨
- 일반 함수로 호출되면 this는 전역객체를 가리킴
- strict mode + 일반함수 호출 -> this는 undefined를 가리킴
- 콜백함수 외부 this와 콜백함수 내부의 this가 차이가 생김
콜백 함수 내/외부 this를 일치 시키는 방법
- 방법01: 외부에서 this를 변수에 할당시켜 받아서, 내부에서 변수을 참조하여 사용
- 방법02: 두번째 인수를 콜백함수 내부의 this로 사용할 객체를 전달하는 기능이 있는 함수를 사용
- ex) Array.prototype.map(callback, this)
- 방법03: Function.prototype.bind 메서드 활용하여 콜백함수에 bind를 붙여 외부 this를 바인딩
- bind() : 내부 this에 바인딩 될 값을 지정함 (.bind(this) -> 외부 this를 바인딩)
- 방법04: 화살표 함수를 사용하기
- 화살표 함수는 자체 this 바인딩이 없어 this 사용시 상위 스코프의 this를 그대로 참조하는 특성을 가졌음
lexical this
: 화살표 함수의 this의 기능을 가진 this를 말함- 렉시컬 스코프처럼, 화살표 함수가 정의된 위치에 의해 this가 결정되는 것
- 화살표 함수가 중첩되어 있는 경우 -> 화살표 함수가 아닌 가장 가까운 함수의 this를 참조
- 화살표 함수의 경우 this 바인딩이 없기 때문에 call, apply, bind 메서드를 사용해도 this 지정이 불가함
- 콜백함수가 함수 표현식으로 작성된 경우, 콜백함수는 일반 함수로 호출 됨
// 화살표 함수의 this 바인딩
// call을 통해서 외부 함수의 this가 정해짐 -> 화살표 함수 this 검색을 통한 this 참조가 일어남
(function () {
const foo = () => console.log(this);
foo();
}.call({ a: 1 })); // { a: 1 }
// 화살표 함수 중첩인 경우 this 검색
(function () {
const bar = () = () => console.log(this);
bar();
}.call({ a: 1 })); // { a: 1 }
// 화살표 함수에서 call, apply, bind 메서드 무시 (this가 없으므로)
window.x = 1
const normal = function() {return this.x}
const arrow = () => this.x
console.log(normal.call({x: 10})) // 10
console.log(arrow.call({x: 10})) // 1
프로토타입 객체의 프로퍼티에 함수를 넣는 경우
- 화살표 함수로 할당하는 경우 화살표 함수의 this는 window를 가리킴
- 함수 표현식을 할당하는 경우 this는 호출된 인스턴스를 가리킴
- ES6 메서드를 사용하는 경우 프로토타입 객체에 새로운 객체를 할당하는 방식으로 ES6메서드를 사용하고, constructor 프로퍼티를 만들어서 생성자 함수간의 연결을 해줘야 함
클래스 필드에 화살표 함수 할당
- 클래스 필드에 this를 포함하는 화살표 함수를 할당하는 경우 -> 예외적으로 this는 인스턴스를 가리킴
- 이 상황에서 화살표 함수의 상위 스코프는 클래스 외부임
- 클래스 필드에 this를 포함하는 화살표 함수를 할당하는 경우 -> 예외적으로 this는 인스턴스를 가리킴
클래스의 constructor 메서드에 화살표 함수 할당
- 클래스 필드와 마찬가지로 this가 인스턴스를 가리킴
화살표 함수의 super
- 화살표 함수는 함수 자체 super 바인딩이 없어 화살표 함수 자신 자체의 super를 사용할 수 없음
- 화살표 함수에서 super 참조시 this와 마찬가지로 상위 스코프 contructor의 super참조
- super은 [[HomeObject]]를 갖는 ES6 메서드 내에서만 사용할수 있는 키워드임
- 클래스 필드에 super를 참조하는 화살표 함수를 할당하면, constructor 내부의 super를 바인딩을 참조함
- 클래스 필드를 사용하면, constructor를 생략해도 암묵적으로 constructor가 생성되므로
화살표 함수의 arguments
- 화살표 함수는 arguments 바인딩이 없어서 화살표 함수 자체의 arguments 객체를 사용할 수 없음
- 상위 스코프의 arguments를 참조함
- arguments가 작용되더라도 상위 스코프 arguments 객체인 것임
Rest 파라미터
Rest 파라미터
: 함수에 전달된 인수들의 목록을 배열로 전달 받음...매개변수
의 형태로 매개변수를 작성함- Rest 파라미터는 반드시 마지막 파라미터이어야 함
- Rest 파라미터는 단 하나만 선언 가능함
- 일반 매개 변수와 rest 파라미터를 함께 사용할 수 있음
- 인수는 매개변수, rest 파라미터 순차적으로 할당 됨
- 매개변수는 매개변수 대로 인수가 들어가고, rest 파라미터 순서 부터는 rest 파라미터에 할당됨 (rest 파라미터에는 매개변수의 인수는 제외 됨)
- Rest 파라미터는 함수객체의 length 프로퍼티에 포함되지 않음
- length 프로퍼티 : 함수정의시 선언한 매개변수의 개수
Rest 파라미터 vs arguments 객체
비교 | Rest 파라미터 | arguments 객체 |
---|---|---|
개념 | 인수 정보 O | 인수 정보 O |
표현 | ...매개변수 | 자동 생성됨 |
반환 | 배열 객체 | 유사 배열 객체 |
배열 메서드 | 직접 사용 가능 | call, apply로 간접적으로 사용해서 변환 필요 |
함수 내부 지역변수 사용 |
O (매개변수) | O(arguments) |
(ES6)단축 메서드 | O | O |
화살표 함수 | O | X |
기본값 지정 기능 | X | O (영향 안받기 때문) |
매개변수 기본값
- JS 엔진은 매개변수와 인수의 개수를 체크 X -> error 발생 X
- 인수가 전달되지 않은 매개변수 : undefined
- 기존 논리 연산자를 통한 인수 체크 및 기본값 설정 방식 (or 연산자)
- ES6의 인수체크 및 초기화
- 매개변수에 할당 연산자를 통해서 값을 할당하는 표현으로 사용함
- 인수전달 안한 경우, undefined 전달한 경우에만 기본값이 작용됨
- rest 파라미터는 ES6 방식 기본값 설정 불가
- arguments객체 영향 받지 않음 (기본값 사용 가능)
function sum1(x, y) {
x = x || 0;
y = y || 0;
return x + y;
}
console.log(sum1(1, 2)); // 3
console.log(sum1(1)); // 1
function sum2(x = 0, y = 0) {
return x + y;
}
console.log(sum2(1, 2)); // 3
console.log(sum2(1)); // 1