💻자바스크립트.js 시리즈는 자바스크립트에 대해 심플하게 훑어봅니다📖
자바스크립트에서 가장 중요한 개념은 바로 함수입니다.
자바스크립트의 함수는 모듈화 처리나 클로저, 객체 생성 등 많은 기능을 제공합니다.
일반 객체와 배열처럼 함수 역시 선언하는 방법이 있습니다.
총 3가지 방법이 있는데, 이들 모두는 같은 함수를 생성하지만
각각 방식에 따라 함수 동작이 미묘하게 차이납니다.
함수를 정의하는데 있어 먼저 알아둬야하는 중요한 개념이 있습니다.
바로 호이스팅입니다.
호이스팅이란 변수나 함수가 어디서 선언되든지, 해당 스코프 최상단에 있어 어디서든 참조할 수 있는 걸 말합니다.
add1(10, 5);
// 15
add2(10, 5);
// 15
function add1(a, b) {
return a + b
}
function add2(a, b) {
return a + b
}
위의 상황도 호이스팅의 예 중 하나입니다.
밑에서 선언했음에도 불구하고 add1과 add2 함수가 올바르게 호출됐습니다.
객체, 배열과 마찬가지로 함수도 표기법이 존재합니다.
function, 함수명, 매개변수 리스트, 함수 몸체가 그것입니다.
function add(x, y) {
return x + y;
}
위와 같은 방식이 바로 함수 선언문입니다.
자바스크립트에서는 함수가 값으로 취급 됩니다. (일급 객체)
따라서 함수도 숫자나 문자열처럼 변수에 할당하는 것도 가능합니다.
함수 표현식은 ES6의 Arrow function 방식입니다.
const add = function(x, y) {
return x + y;
}
// es6
const add = (x, y) => x + y;
add(5, 5)
// 10
여기서 나타나는 재밌는 점은 사실 함수의 함수명이 선택사항이란 점입니다.
함수 선언문의 경우는 예외로 반드시 함수명이 명시되어야 하지만
함수 표현식에선 선택사항이됩니다.
함수 표현식을 다른 말로 익명 함수라고 부르기도 합니다.
객체에선 Object, 배열에선 Array라는 생성자 함수가 존재했습니다.
함수에도 역시 Function이라는 키워드가 존재합니다.
생성자 함수는 꼭 new를 붙여 사용합니다.
const add = new Function('x', 'y', 'return x + y');
add(5, 5);
// 10
하지만 선언문은 거의 쓰이지 않습니다. 성능적으로도 좋지 않기 때문입니다.
앞서 호이스팅에 대해 간략하게 살펴봤습니다.
호이스팅은 장점도 있겠지만 함수를 선언하기도 전에 차용하는 방식을 취하기 때문에
코드의 구조가 엉성하게 될 수 있습니다. 그래서 더글러스 크락포드는 함수 표현식만을 사용할 것을 권하고 있습니다.
add1(10, 5);
// 15
add2(10, 5);
// 15
function add1(a, b) {
return a + b
}
function add2(a, b) {
return a + b
}
이전에 살펴본 위의 코드에서 함수를 함수 표현식으로 바꾸면 호이스팅이 제거됩니다.
add1(10, 5);
// Cannot access 'add1' before initialization
add2(5, 5);
// Cannot access 'add2' before initialization
const add1 = (a, b) => a + b;
const add2 = (a, b) => a + b;
함수는 객체입니다. 그렇기 때문에 프로퍼티도 가질 수 있습니다.
function add(x, y) {
return x + y;
}
add.results = 5;
console.log(add.results);
// 5
함수는 일반 객체이기 때문에 변수나 배열의 요소, 객체의 프로퍼티 등에 할당이 가능하고 함수의 인자나 리턴 값으로 반환이 되며 동적으로 프로퍼티를 생성하고 할당이 가능합니다.
이러한 점은 자바스크립트가 함수형 프로그래밍을 할 수 있는 원동력이 됩니다.
모든 함수는 객체로서 prototype 프로퍼티를 갖고 있습니다.
그리고 prototype에는 constructor라는 프로퍼티를 갖고 있습니다.
여기서 조금 복잡해지는데요,
함수의 prototype은 constructor와 함께 부모로 Object prototype도 가집니다.
그리고는 함수 자체의 위에서도 Object Prototype를 가지게 됩니다.
이런 이유는 함수가 constructor라는 생성자를 통해 객체를 만들 수 있기 때문입니다.
생성된 객체 역시 객체이기 때문에 Object Prototype이 필요하겠죠.
그래서 생성자로 만들어진 객체를 위해 Object Prototype을 안에 갖고 태어나고, 함수 자체도 객체이기 때문에 Object Prototype을 갖게 되는 것입니다.
콜백 함수란 위에서 언급한 함수 표현식을 활용하는 대표적인 예입니다.
여기서 콜백 함수란 개발자가 어떤 조건을 내걸고, 그 조건에 맞으면 발동하는 함수를 일컫습니다.
가장 쉬운 예로 이벤트 핸들러가 있습니다.
내부 함수는 함수 코드 내부에서도 함수를 정의하는 걸 말합니다.
이런 기능은 클로저 등 자바스크립트의 대표적인 기능들을 구현하는 데 핵심적인 역할을 합니다.
function add(a, b) {
const c = a + b;
function plusOne() {
console.log(c + 1);
}
console.log(c);
plusOne();
}
add(2, 3);
// 5
// 6
내부 함수는 자신이 정의된 부모 안에서 호출이 가능한데요, 변수 역시 마찬가지입니다.
바로 이러한 기능을 클로저라고 합니다.
예제에서 add는 plusOne이라는 새로운 함수를 만들었고 내부에서 실행합니다.
그리고 plusOne은 c라는 변수를 부모에게서 끌어와 인자가 없음에도 +1을 할 수 있었습니다.
만약 여기서 return 값으로 plusOne 함수를 반환한다면. 어떻게 될까요?
function add(a, b) {
const c = a + b;
function plusOne() {
return c + 1;
}
return plusOne();
}
const newAdd = add(3, 3);
console.log(newAdd);
// 7
add 함수는 3과 3을 받아 c라는 변수에 6을 저장했고 동시에 plusOne() 함수를 실행해 +1을 했습니다.
newAdd 변수에 함수를 저장하니, 7이라는 결과값을 얻었습니다.
바로 이러한 역할이 클로저의 역할이라 할 수 있겠습니다.
객체, 배열에 이어 함수까지 훑어봤습니다!
이제 아마 많은 자바스크립트 개발자들이 좌절하는 call, apply, 그리고 this 바인딩에 대해 알아보겠습니다!🙂
출처
- 인사이드 자바스크립트
- 함수형 자바스크립트 프로그래밍