탱구탱구 개발자 일기

ECMAScript 6부터 함수 리터럴을 화살표 함수(Arrow Function)라는 표현식으로 단축 표현이 가능해졌다. 그러나 함수 리터럴과 차이점이 있으니 이 점을 주의해야 한다.

 

[화살표 함수]

화살표 함수의 기본적인 표현식은 다음과 같다.

// 화살표 함수 표현식

// 화살표 함수는 함수 리터럴(익명함수)의 단축 표현

// 함수 리터럴
let a = function(x) {
    return x * x;
}

// 화살표 함수
let a = (x) => {
    return x * x
};

// 인수가 하나일 때 인수 묶는 소괄호 생략
let a = x => {
    return x * x;
}

// 인수 여러개
let b = (x, y, z) => {
    return x + y + z;
}

// 인수가 없다면 소괄호 생략 불가
let c = () => {
    return false;
}

// 함수 코드가 return 뿐일때 중괄호, return 생략가능
let d = x => x * x;

// 반환값이 객체 리터럴이면 객체 리터럴을 그룹연산자 ()로 묶어야함
let e = (x, y) => ({a: x, b: y});

// 즉시 실행 함수
(x => x * x)(10; // 100

 

[함수 리터럴과 화살표 함수의 차이점]

 

1. this의 값이 함수를 정의할 때 결정

함수 리터럴로 정의한 함수의 this는 함수를 호출할 때 결정된다. 그러나 화살표 함수의 this는 함수를 정의할 때 결정된다. 이는 화살표 함수 바깥의 this값이 화살표 함수의 this값으로 참조된다는 것을 말한다.

let obj = {
    hello: function () {
        console.log('hello:', this); //hello: {hello: ƒ}
        let x = function () {
            console.log('x:', this); //x: Window {…}
        }
        x();
        let y = () => console.log('y:', this); //y: {hello: ƒ}
        y();
    }
};
obj.hello();

함수 리터럴로 정의된 x는 중첩 함수이다. 중첩 함수의 this는 전역 객체를 가리키므로 this는 window가 찍힌다. 화살표 함수로 정의된 y는 hello 메서드가 정의된 this를 말한다. 즉, obj 객체를 가리킨다.

 

화살표 함수는 call이나 apply 메서드를 사용하여 this를 바꿔 호출해도 this값이 변하지 않는다. 아래 코드에서도 화살표 함수의 참조를 값고 있는 객체 cc를 call 메서드를 사용해서 호출했는데 값이 아무 것도 나오지 않는다. 해당 메서드를 사용해도 this를 바꿀 수 없기 때문에 화살표 함수 console.log에서 this는 언제나 상위 스코프의 this인 window를 가리킨다. window 객체에는 name이라는 프로퍼티가 없고 아무 값도 나오지 않는다.

let bb = function () {
    console.log(this.name);
}

let cc = () => console.log(this.name);

let oh = {
    name: "준영"
};

bb.call(oh); // 준영
cc.call(oh); // ""

 

2. arguments 변수가 없다.

 

화살표 함수 안에는 arguments 변수가 정의되어 있지 않으므로 사용할 수 없다.

let a = (a, b) => console.log(arguments);
a(); // Uncaught ReferenceError: arguments is not defined

// 함수 리터럴
let b = function (a, b) {
    console.log(arguments);
}
b(); // Arguments [callee: ƒ, Symbol(Symbol.iterator): ƒ]

 

3. 생성자로 사용할 수 없다.

// 3. 생성자로 사용할 수 없다.

// 화살표 함수
let Animal = (name, type) => {
    this.name = name;
    this.type = type;
};

let mammal = new Animal("호랑이", "육식동물"); // Uncaught TypeError: Animal is not a constructor

// 함수 리터럴
let Animal = function (name, type) {
    this.name = name;
    this.type = type;
};

let mammal = new Animal("호랑이", "육식동물"); // Animal{name: "호랑이", type: "육식동물"}

 

4. yield 키워드를 사용할 수 없다.

 

화살표 함수는 yield 키워드를 사용할 수 없으므로 제너레이터로 사용할 수 없다. 이 부분은 자바스크립트 이터레이터를 배운 후 정리하도록 하겠다.

 

[객체 리터럴에서 화살표 함수로 메서드를 정의]

 

화살표 함수로 메서드를 정의하면 그 안의 this의 경우 상위 스코프인 전역 객체 window를 가리킨다. 따라서 화살표 함수로 객체 리터럴 안에서 메서드를 정의하는 것은 사용되지 않는다. 일반 함수를 통해 메서드를 정의하자.

// 객체 리터럴에서 화살표 함수로 메소드 정의
let person = {
    name: '탱구탱구',
    sayHello: () => console.log(`${this}`)
};

person.sayHello(); // Object Window

[객체의 Prototype에서 화살표 함수로 메서드를 정의]

 

객체 리터럴에서 화살표 함수로 메서드를 정의한 것과 동일하게 전역 객체 window를 가리킨다.

// Prototype에서 화살표 함수로 메서드 정의
function Person(name) {
    this.name = name;
}

Person.prototype.sayHello = () => {
    console.log("안녕:", this);
}

let person = new Person("탱구탱구12");
person.sayHello(); // 안녕: Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}

 

이 글을 공유합시다

facebook twitter kakaoTalk kakaostory naver band
loading