arrow function 화살표 함수의 호출 화살표 함수와 function으로 생성한 함수의 차이점 화살표 함수를 사용하면 안되는 경우 Vue에서 화살표 함수 사용방법 결론: Vue에서의 화살표 함수 및 일반 함수 사용 방법


화살표 함수는 기존의 function 키워드 대신 화살표(=>)를 사용하여, 보다 간단히 함수를 선언하는 방식이다. 문법은 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 매개변수 지정 방법
() => { ... } // 매개변수가 없을 경우
x => { ... } // 매개변수가 한 개인 경우, 소괄호를 생략할 수 있다.
(x, y) => { ... } // 매개변수가 여러 개인 경우, 소괄호를 생략할 수 없다.

// 함수 몸체 지정 방법
x => { return x * x } // single line block
x => x * x // 함수 몸체가 한줄의 구문이라면 중괄호를 생략할 수 있으며 암묵적으로 return된다. 위 표현과 동일하다.

() => { return { a: 100 }; }
() => ({ a: 100 }) // 위 표현과 동일하다. 객체는 반환할 때, 소괄호를 사용한다.

() => { // multi line block.
const x = 100;
return x * x;
};

화살표 함수의 호출


화살표 함수는 익명 함수로만 사용할 수 있기 때문에, 화살표 함수를 호출하기 위해서는 함수 표현식을 사용해야 한다.

1
2
3
4
5
6
7
// ES5
var pow = function (x) { return x * x; };
console.log(pow(5)); // 25

// ES6
const pow = x => x * x;
console.log(pow(5)); // 25

콜백함수에서도 화살표 함수를 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
// ES5
var arr = [2, 4, 6];
var pow = arr.map(function (x) { // x는 요소값
return x * x;
});

console.log(pow); // [ 4, 16, 36 ]

// ES6
const arr = [2, 4, 6];
const pow = arr.map(x => x * x);

console.log(pow); // [ 4, 16, 36 ]

화살표 함수와 function으로 생성한 함수의 차이점


두 방식의 가장 큰 차이점은 this 이다.

  • function 함수: 생성자 함수와 객체의 메소드를 제외한 모든 함수(내부 함수, 콜백 함수 포함) 내부의 this는 전역 객체를 가리킨다.
  • 화살표 함수: 언제나 상위 스코프의 this를 가리킨다.

function 키워드로 생성한 함수의 this


Javascirpt에서의 this는 함수를 호출할 때 함수가 어떻게 호출되었는지에 따라 this에 바인딩할 객체가 동적으로 결정된다. Javascript에서의 this를 참고한다.

생성자 함수와 객체의 메소드를 제외한 모든 함수(내부 함수, 콜백 함수 포함) 내부의 this는 전역 객체를 가리키기 때문이다. 즉, 콜백 함수 내부의 this는 전역 객체 window를 가리킨다.

1
2
3
4
5
6
7
8
9
10
11
12
13
function Prefixer(prefix) {
this.prefix = prefix;
}

Prefixer.prototype.prefixArray = function (arr) {
// (1)
return arr.map(function (x) {
return this.prefix + ' ' + x; // (2)
});
};

var pre = new Prefixer('Hi');
console.log(pre.prefixArray(['Ro', 'Park']));

위치에 따라 this의 값은 달라진다.

  • (1): 여기서, this는 생성자 함수 Prefixer가 생성한 객체, 즉 생성자 함수의 인스턴스(위 예제의 경우 pre)이다.
  • (2): 여기서, this는 전역 객체 window를 가리킨다.

콜백 함수 내부의 this가 메소드를 호출한 객체(생성자 함수의 인스턴스)를 가리키게 하는 3가지 방법이 있다.

  1. that = this
  2. map(func, this)
  3. bind(this)
  1. that = this

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function Prefixer(prefix) {
    this.prefix = prefix;
    }

    Prefixer.prototype.prefixArray = function (arr) {
    var that = this; // this: Prefixer 생성자 함수의 인스턴스
    return arr.map(function (x) {
    return that.prefix + ' ' + x;
    });
    };

    var pre = new Prefixer('Hi');
    console.log(pre.prefixArray(['Lee', 'Kim']));
  2. map(func, this)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function Prefixer(prefix) {
    this.prefix = prefix;
    }

    Prefixer.prototype.prefixArray = function (arr) {
    return arr.map(function (x) {
    return this.prefix + ' ' + x;
    }, this); // this: Prefixer 생성자 함수의 인스턴스
    };

    var pre = new Prefixer('Hi');
    console.log(pre.prefixArray(['Lee', 'Kim']));
  3. bind(this)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function Prefixer(prefix) {
    this.prefix = prefix;
    }

    Prefixer.prototype.prefixArray = function (arr) {
    return arr.map(function (x) {
    return this.prefix + ' ' + x;
    }.bind(this)); // this: Prefixer 생성자 함수의 인스턴스
    };

    var pre = new Prefixer('Hi');
    console.log(pre.prefixArray(['Ro', 'Park']));

화살표 함수의 this


화살표 함수의 this는 언제나 상위 스코프의 this를 가리킨다.

1
2
3
4
5
6
7
8
9
10
11
function Prefixer(prefix) {
this.prefix = prefix;
}

Prefixer.prototype.prefixArray = function (arr) {
// this는 상위 스코프인 prefixArray 메소드 내의 this를 가리킨다.
return arr.map(x => `${this.prefix} ${x}`);
};

const pre = new Prefixer('Hi');
console.log(pre.prefixArray(['Ro', 'Park']));

화살표 함수는 call, applay, bind 메소드를 사용하여 this를 변경할 수 없다.

1
2
3
4
5
6
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

화살표 함수를 사용하면 안되는 경우


화살표 함수는 Lexical this를 지원하므로 콜백 함수로 사용하기 편리하지만, 화살표 함수를 사용하지 말아야 하는 경우도 있다.

<1> 메소드


메소드를 정의할 때는, 화살표 함수를 사용하면 안된다.

1
2
3
4
5
6
const person = {
name: 'Ro',
sayHi: () => console.log(`Hi ${this.name}`)
};

person.sayHi(); // Hi undefined

위와 같이, sayHi라는 메소드를 정의할 때 화살표 함수를 사용하게 되면, 화살표 함수 내부의 this는 상위 컨택스트인 전역 객체 window를 가리킨다.

ES6의 축약 메소드 표현을 사용하면, 다음과 같이 작성할 수 있다.

1
2
3
4
5
6
7
8
const person = {
name: 'Ro',
sayHi() { // === sayHi: function() {
console.log(`Hi ${this.name}`);
}
};

person.sayHi(); // Hi Ro

<2> prototype


prototype에 할당하기 위한 메소드를 정의할 때는, 화살표 함수를 사용하면 안된다.

1
2
3
4
5
6
7
const person = {
name: 'Ro',
};

Object.prototype.sayHi = () => console.log(`Hi ${this.name}`);

person.sayHi(); // Hi undefined

prototype에 메소드를 할당하는 경우, 일반 함수를 사용해야 한다.

1
2
3
4
5
6
7
8
9
const person = {
name: 'Ro',
};

Object.prototype.sayHi = function() {
console.log(`Hi ${this.name}`);
};

person.sayHi(); // Hi Ro

<3> 생성자 함수


생성자 함수를 사용할 때는, 화살표 함수를 사용하면 안된다. 생성자 함수는 prototype 프로퍼티를 가지며 prototype 프로퍼티가 가리키는 프로토타입 객체의 constructor를 사용한다. 그러나, 화살표 함수는 prototype 프로퍼티를 가지고 있지 않다.

1
2
3
4
5
6
const Foo = () => {};

// 화살표 함수는 prototype 프로퍼티가 없다
console.log(Foo.hasOwnProperty('prototype')); // false

const foo = new Foo(); // TypeError: Foo is not a constructor

<4> addEventListener 함수의 콜백 함수


addEventListener 함수의 콜백 함수를 사용할 때는, 화살표 함수를 사용하면 안된다.

만약, addEventListener 함수의 콜백 함수를 화살표 함수로 정의하면, 화살표 함수 내의 this는 상위 컨택스트인 전역 객체 window를 가리킨다.

1
2
3
4
5
6
var button = document.getElementById('myButton');

button.addEventListener('click', () => {
console.log(this === window); // => true
this.innerHTML = 'Clicked button';
});

그래서, addEventListener 함수의 콜백 함수를 사용할 때는, 일반 함수인 function 키워드를 사용해야 한다. 일반 함수로 정의된 addEventListener 함수의 콜백 함수 내부의 this는 이벤트 리스너에 바인딩된 요소(currentTarget)를 가리킨다.

1
2
3
4
5
6
var button = document.getElementById('myButton');

button.addEventListener('click', function() {
console.log(this === button); // => true
this.innerHTML = 'Clicked button';
});

Vue에서 화살표 함수 사용방법


Vue에서 화살표 함수는 기본적으로 ES6에서의 화살표 함수와 동일하다.

화살표 함수의 사용 여부에 대한 대표적인 경우는 2가지이다.

  • 메소드를 정의할 때
  • 콜백함수를 정의할 때

Vue에서 메소드를 정의할 때


Vue에서 메소드를 정의할 때는, 화살표 함수를 사용하면 안된다. 즉, function 키워드를 사용하는 일반 함수로 정의해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<div>
<input type="text" v-model="newTodo">
<button v-on:click="addTodo">add</button>
</div>
</template>

<script>
export default {
data: () => ({
newTodo: ''
}),
methods: {
addTodo: function () {
console.log(this.newTodo); // input에서 입력한 값을 가져옴
}
}
}
</script>

methods에서 addTodo를 정의할 때, function 키워드를 사용하면, 이 함수내의 this는 Vue 인스턴스를 가리킨다. 그래서, this.newTodo의 값을 가져올 수 있다.

만약, 화살표 함수로 addTodo를 정의하면 어떻게 될까?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<div>
<input type="text" v-model="newTodo">
<button v-on:click="addTodo">add</button>
</div>
</template>

<script>
export default {
data: () => ({
newTodo: ''
}),
methods: {
addTodo: () => {
console.log(this.newTodo); // undefined
}
}
}
</script>

화살표 함수로 addTodo를 정의하면, 이 함수내의 this는 전역객체 window를 가리킨다. 그래서 값이 undefined가 된다.

대신, ES6의 축약 메소드 표현을 사용하면, 다음과 같이 작성할 수 있다.

1
2
3
4
5
methods: {
addTodo () {
console.log(this.newTodoItem) // input에서 입력한 값을 가져옴
}
}

Vue에서 콜백 함수를 정의할 때


Vue에서 콜백 함수를 정의할 때, 화살표 함수를 사용하면, 정의된 콜백 함수내의 this는 Vue의 인스턴스를 가리킨다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script>
export default {

data: {
size: 'small',
items: [ { size: 'small' }, { size: 'large' } ]
},

computed: {
filterBySize() {
return this.items.filter((item) => {
return item.size === this.size; // this는 Vue의 인스턴스를 가리킴
});
}
}

}
</script>

만약, 콜백 함수를 정의할 때, function 키워드를 사용하면, 정의된 콜백 함수내의 this는 상위 컨택스트, 즉 전역 객체 window를 가리킨다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script>
export default {

data: {
size: 'small',
items: [ { size: 'small' }, { size: 'large' } ]
},

computed: {
filterBySize() {
let size = this.size // 여기서 this는 Vue 인스턴스를 가리키기 때문에, 미리 size라는 변수에 위 data의 size의 값을 할당
return this.items.filter(function(item) {
return item.size === size;
});
}
}

}
</script>

결론: Vue에서의 화살표 함수 및 일반 함수 사용 방법


  • 메소드를 정의할 때는, 일반 함수를 사용한다. 이때, funtion 키워드르 안쓰고 싶다면, ES6의 축약 메소드 표현을 사용해서, 간단히 작성하면 된다.
  • 콜백 함수를 정의할 때는, 화살표 함수를 사용한다. 이때, 정의된 콜백 함수내의 this는 해당 컨택스트, 즉 정의된 콜백 함수를 가지고 있는 Vue 인스턴스를 가리킨다.