1. 함수의 구분( ES6 이전 버전에서의 문제점 )
ES6 이전의 모든 함수는 callable이면서 constructor입니다.
ES6 이전의 모든 함수는 일반 함수로서 호출할 수 있는 것은 물론 생성자 함수로서 호출할 수 있습니다.
아래 예제와 같이 ES6 이전의 함수는 동일한 함수라도 다양한 형태로 호출할 수 있습니다.
var foo = function () {
return 1;
};
// 일반적인 함수로서 호출
foo(); // -> 1
// 생성자 함수로서 호출
new foo(); // -> foo {}
// 메서드로서 호출
var obj = { foo: foo };
obj.foo(); // -> 1
주의할 것은 ES6 이전에 일반적으로 메서드라고 부르던 객체에 바인딩된 함수도 callable이며 constructor라는 것입니다.
일반적으로 객체에 바인딩된 함수를 생성자 함수로 호출하는 경우가 흔치 않겠지만
아래 예제 코드와 같은 것이 문법상 가능하다는 것은 성능 면에서도 문제가 있습니다.
// 프로퍼티 f에 바인딩된 함수는 callable이며 constructor다.
var obj = {
x: 10,
f: function () { return this.x; }
};
// 프로퍼티 f에 바인딩된 함수를 메서드로서 호출
console.log(obj.f()); // 10
// 프로퍼티 f에 바인딩된 함수를 일반 함수로서 호출
var bar = obj.f;
console.log(bar()); // undefined
// 프로퍼티 f에 바인딩된 함수를 생성자 함수로서 호출
console.log(new obj.f()); // f {}
객체에 바인딩된 함수가 constructor라는 것은 객체에 바인딩된 함수가 prototype 프로퍼티를 가지며, 프로토타입 객체도 생성한다는 것을 의미하기 때문입니다. 콜백 함수도 마찬가지로 constructor이므로 불필요한 프로토타입 객체를 생성합니다.
이처럼 ES6 이전의 모든 함수는 사용 목적에 따라 명확한 구분이 없으므로 호출 방식에 특별한 제약이 없고 생성자 함수로 호출하지 않아도 프로토타입 객체를 생성합니다.
이러한 문제를 해결하기 위해 ES6에서는 함수를 사용 목적에 따라 세 가지 종류로 명확히 구분했습니다.
| ES6 함수의 구분 | constructor | prototype | super | arguments |
| 일반 함수(Normal) | ⭕ | ⭕ | ❌ | ⭕ |
| 메서드(Method) | ❌ | ❌ | ⭕ | ⭕ |
| 화살표 함수(Arrow) | ❌ | ❌ | ❌ | ❌ |
2. 메서드
ES6 메서드는 본연의 기능(super)을 추가하고 의미적으로 맞지 않는 기능(constructor)은 제거했습니다.
(1) ES6 사양에서 메서드는 메서드 축약 표현으로 정의된 함수만을 의미합니다.
(2) ES6 사양에서 정의한 메서드는 인스턴스를 생성할 수 없는 non-constructor입니다.
const obj = {
x: 1,
// foo는 메서드이다.
foo() { return this.x; },
// bar에 바인딩된 함수는 메서드가 아닌 일반 함수이다.
bar: function() { return this.x; }
};
console.log(obj.foo()); // 1
console.log(obj.bar()); // 1
// ES6 메서드 축약표현만 메서드로 인정된다.
const obj = {
name: 'Lee',
// 메소드 축약 표현
sayHi() {
console.log('Hi! ' + this.name);
}
};
obj.sayHi(); // 일반함수 호출: Hi! Lee
// ES5
var obj = {
name: 'Lee',
// 프로퍼티 sayHi의 값으로 할당된 것은 일반 함수(constructor)로 정의된 함수이다.
// 현재 ECMAScript 사양에서 메서드로 인정되지 않는다.
sayHi: function() {
console.log('Hi! ' + this.name);
}
};
obj.sayHi(); // Hi! Lee
// ES5의 메서드 선언 방식은 현재 ECMAScript 사양에서는 일반 함수로 정의된다.
// 일반 함수는 constructor이므로 new로 인스턴스를 생성할 수 있다.
new obj.sayHi(); // sayHi {}
(3) ES6 메서드는 자신을 바인딩한 객체를 가리키는 내부 슬롯 [[HomeObject]]을 가집니다.
따라서 super 키워드를 사용할 수 있습니다.
ES6에서 메서드가 아닌 함수는 super 키워드를 사용할 수 없습니다.
const base = {
name: 'Lee',
sayHi() {
return `Hi! ${this.name}`;
}
};
const derived = {
__proto__: base,
// sayHi는 ES6 메서드다. ES6 메서드는 [[HomeObject]]를 갖는다.
// sayHi의 [[HomeObject]]는 sayHi가 바인딩된 객체인 derived를 가리키고
// super는 sayHi의 [[HomeObject]]의 프로토타입인 base를 가리킨다.
sayHi() {
return `${super.sayHi()}. how are you doing?`;
}
};
console.log(derived.sayHi()); // Hi! Lee. how are you doing?
3. 화살표 함수
화살표 함수는 function 키워드 대신 화살표(=> fat arrow) 를 사용하여 기존의 함수 정의 방식보다 간략하게 함수를 정의할 수 있습니다. 표현만 간단해지는 것이 아니라 내부 동작도 기존 함수보다 간단합니다.
특히, 화살표 함수는 콜백 함수 내부에서 this가 전역 객체를 가리키는 문제를 해결하기 위한 대안이 되는게 중요한 특징입니다.
(1) 화살표 함수의 문법
(1.1) 기본적인 사용법
화살표 함수는 =>(화살표) 기호를 사용하여 함수를 정의합니다.
const 함수이름 = (매개변수1, 매개변수2) => 표현식;
(1.2) 매개변수가 하나일 경우 괄호 생략 가능
const square = x => x * x;
console.log(square(5)); // 25
(1.3) 매개변수가 없을 경우 괄호 필수
const greet = () => "Hello, world!";
console.log(greet()); // "Hello, world!"
(1.4) 여러 개의 표현식을 사용할 경우 중괄호 사용
중괄호 {}를 사용하면 명시적으로 return 키워드를 사용해야 합니다.
const add = (a, b) => {
const result = a + b;
return result;
};
console.log(add(3, 7)); // 10
(2) 화살표 함수와 this
화살표 함수는 기존의 함수와 다르게 자신만의 this를 가지지 않습니다.
즉, 화살표 함수 내부의 this는 상위 스코프의 this를 그대로 사용합니다.
(2.1) 일반 함수의 this 바인딩 문제
function Person(name) {
this.name = name;
this.sayHello = function() {
setTimeout(function() {
console.log(`Hello, my name is ${this.name}`);
}, 1000);
};
}
const person = new Person("Alice");
person.sayHello(); // undefined (this가 Window 또는 undefined를 참조)
위 코드에서 setTimeout 내부의 function은 this를 Person 객체가 아니라 전역 객체(브라우저에서는 window 객체, Node.js에서는 global 객체)를 가리키기 때문에 undefined가 출력됩니다.
(2.2) 화살표 함수를 사용한 해결
function Person(name) {
this.name = name;
this.sayHello = function() {
setTimeout(() => {
console.log(`Hello, my name is ${this.name}`);
}, 1000);
};
}
const person = new Person("Alice");
person.sayHello(); // "Hello, my name is Alice"
화살표 함수는 this를 새롭게 바인딩하지 않고 상위 스코프(Person 객체)의 this를 사용하기 때문에 원하는 결과가 출력됩니다.
(3) 화살표 함수와 arguments
일반 함수에서는 arguments 객체를 사용하여 전달된 모든 인수를 참조할 수 있지만,
화살표 함수는 arguments를 지원하지 않습니다.
function normalFunction() {
console.log(arguments);
}
normalFunction(1, 2, 3); // [1, 2, 3]
const arrowFunction = () => {
console.log(arguments);
};
arrowFunction(1, 2, 3); // 오류 발생 (arguments is not defined)
대신, Rest Parameter(...args)를 사용하면 동일한 기능을 구현할 수 있습니다.
const arrowFunction = (...args) => {
console.log(args);
};
arrowFunction(1, 2, 3); // [1, 2, 3]
(4) Rest 파라미터(Rest Parameter)
Rest 파라미터(...args)는 함수의 매개변수 개수가 정해지지 않았을 때 유용하게 사용할 수 있습니다.
const sum = (...numbers) => numbers.reduce((acc, num) => acc + num, 0);
console.log(sum(1, 2, 3, 4, 5)); // 15
Rest 파라미터는 항상 마지막 매개변수로 와야 하며, 여러 개 사용할 수 없습니다.
const example = (a, b, ...rest) => {
console.log(a, b, rest);
};
example(1, 2, 3, 4, 5); // 1 2 [3, 4, 5]
(5) 화살표 함수의 주의할 점
① 메서드 정의에는 적절하지 않음: 객체의 메서드를 정의할 때는 ES6 메서드를 사용해야 합니다.
const obj = {
value: 10,
method: () => {
console.log(this.value);
}
};
obj.method(); // undefined (this가 obj가 아닌 상위 스코프를 참조)
② 생성자 함수로 사용할 수 없음: new 키워드와 함께 사용할 수 없습니다.
const Person = (name) => {
this.name = name;
};
const p = new Person("Alice"); // 오류 발생
③ call, apply, bind 메소드를 사용 this를 변경할 수 없음: 화살표 함수는 this를 고정하기 때문에 call 등의 메서드로 변경할 수 없습니다.
const obj = {
value: 42
};
const getValue = () => this.value;
console.log(getValue.call(obj)); // undefined
(6) 결론 및 요약
화살표 함수는 간결한 문법과 this 바인딩 특성 때문에 콜백 함수, 비동기 코드, 배열 메서드(map, filter, reduce 등)에서 유용하게 사용할 수 있습니다. 하지만, 메서드 정의나 생성자 함수에는 적합하지 않다는 점을 주의해야 합니다.
✅ 간결한 문법 제공 (중괄호 없이 표현 가능)
✅ this를 상위 스코프에서 상속
✅ arguments 객체를 사용하지 않음 (대신 ...args 사용)
✅ 메서드 정의나 생성자 함수로 부적합
화살표 함수를 적절히 활용하면 더 깔끔하고 직관적인 코드를 작성할 수 있습니다!
해당 게시물은 위 도서를 통해 공부한 내용입니다.
~ 오류나 보완할 점에 대한 조언과 응원은 언제나 감사합니다! ~
'Study Notes > JavaScript' 카테고리의 다른 글
| [JavaScript] 디스트럭처링 할당(구조 분해 할당) (0) | 2025.02.13 |
|---|---|
| [JavaScript] 데이터 타입: number, undefined, null 등 (1) | 2025.02.04 |
| [JavaScript] 변수 (0) | 2025.01.24 |
| [JavaScript] JS 실행 환경: 브라우저와 Node.js (0) | 2025.01.24 |
| [JavaScript] let, var, const와 호이스팅 (0) | 2025.01.24 |
