함수를 선언하고 호출할 때, 일반적인 방법 외에도 자바스크립트에서 다양하게 선언하고 호출할 수 있습니다.
여태까지 봐왔던 일반적인 함수 선언식입니다. function 구문을 이용하여 선언 방식입니다.
function foo() {
// ...
}
이름이 없는 함수로 함수에 이름을 명시적으로 표기하지 않는 선언 방식입니다.
var foo = function () {
// ...
}
함수 선언식과 비교해보면 함수에 name 속성
의 차이로 볼 수 있습니다. 이름을 지정해주지 않는 경우 name 속성
에 빈 문자열이 들어가게 됩니다.
function a() {}
var b = function () {};
var c = function func() {};
a.name; // 'a'
b.name; // ''
c.name; // 'func'
대게 변수에 할당하는 함수에 선언하거나, 객체 내에 있는 메서드에 함수를 선언할 때 함수의 이름이 필요 없기 때문에 익명 함수를 사용합니다.
익명함수를 통해 생성과 동시에 실행시킬 수 있는 함수로, 초기화 정보나 전역공간에 영향없이 사용하기 위해 많이 사용합니다.
(
// 생성
function () {
// ...
}
)(); // 실행
함수가 실행했을 때의 환경을 기억하고 있는 것을 클로저라고 합니다. 함수에서 지역변수는 함수가 종료될 때 같이 사라지게 됩니다. 다음 함수를 반환하게 되는 경우를 확인해보겠습니다.
function sum() {
var a = 10;
return function (b) {
return a + b;
};
}
let res = sum();
res(20); // 30;
res(100); // 110
sum()
함수를 호출된 후에는 a 지역변수가 사라지지 않고 값을 지니고 있다가 반환한 함수의 내부에서 사용되는 것을 볼 수 있습니다. 이러한 형태를 클로저라 합니다.
내부에서는 접근 가능하지만, 외부에서는 접근할 수 없는 private 변수처럼 사용할 수 있습니다.
function Person(name) {
this.getName = function () {
return name;
};
}
var person = new Person('camp-son');
person.getName(); // camp-son
person.name; // undefined
단, 클로저의 경우 환경을 기억하고 있기 때문에 메모리에 존재하게 됩니다. 이는 성능에 영향을 줄 수 있기 때문에 사용이 끝난 클로저는 메모리에서 해제하는 작업을 해줘야 합니다.
Javascript - 3.Function(1)#함수에서 1급 함수
에 대한 설명을 했었습니다. 특징 중 하나인 함수를 함수의 인자로 전달할 수 있습니다. 이 말은 함수를 인자로 받는 함수에서 전달 받은 함수의 실행을 제어할 수 있고 이러한 특성을 활용하여 주로 비동기 처리를 할 때 많이 사용합니다. 대표적으로 자바스크립트의 내장함수인 setTimeout
함수를 볼 수 있습니다.
var count = 0;
function hello() {
console.log('Hello world', count);
count++;
}
setTimeout(hello, 1000); // Hello world 1
hello(); // Hello world 0
setTimeout의 인자로 받은 hello 함수를 콜백함수
라고 합니다. 이렇게 콜백함수는 비동기 처리, 이벤트 핸들러 등 함수의 실행 시점을 특정할 수 없어 함수의 실행을 함수에게 위임하는 형태로 사용됩니다.
단순한 콜백함수의 사용은 단순하여 가독성도 좋지만, 콜백함수를 중첩으로 사용하게 되면 가독성이 많이 떨어지고 테스트가 쉽지 않습니다.
asyncFunc1(function () {
asyncFunc2(function () {
asyncFunc3(function () {
asyncFunc4(function () {
// Processing data
});
});
});
});
위와 같이 콜백함수를 중첩으로 많이 사용하게 되면 asyncFunc4가 실행되기까지의 많은 대기가 필요합니다. 이를 해결하기 위한 방법은 Promise, Generator, async/await 정도가 있는데 이에 대한 부분은 별도로 정리하도록 하겠습니다.
함수를 호출할 때엔 기본적으로 func()
형태로 호출합니다. 자바스크립트의 함수에서는 그 외에 다양한 방법으로 함수를 호출할 수 있는 메서드를 제공하는데 함수의 this와 밀접한 관계가 있습니다.
두가지 메서드는 동일하게 동작하지만, 인자로 받는 값에 차이가 있습니다. call은 두번째 인자부터 순차적으로 인자를 전달해주고, apply는 두번째 인자에 배열형태로 인자를 전달합니다.
function empty(x) {}
empty(10);
empty.call(this, 10);
empty.apply(this, [10]);
위 3가지 방식의 호출은 모두 동일한 결과가 나옵니다.
다른 점은 첫번째 인자로 this가 전달되는 방식인데, 이 this는 다른 OOP 언어와 다르게 인스턴스 자신을 가르키지 않습니다. 함수 내부에서 사용하는 this에 대해 전달하는 것입니다. this에 대한 자세한 내용은 추후 따로 정리할 예정입니다.
function Person(age) {
this.age = age;
this.addAge = function (n) {
this.age += n;
};
}
ver person = new Person(10);
person.addAge(2);
person.age; // 12
var darknight = {age: 40};
person.addAge.call(darknight, 10);
person.age; // 12
darknight.age; // 50
person.addAge.apply(darknight, [5]);
person.age; // 12
darknight.age; // 55
bind는 단순히 함수에 this 객체만 지정해주는 함수입니다. bind 후 호출시 함수에서 연결된 객체를 this로 인지합니다.
함수를 선언하고 사용하는 방식이 다양하지만, 이러한 유연성이 활용을 잘한다면 좋은 퍼포먼스를 낼 수 있을 것으로 생각됩니다. 많은 여러 유형과 그 사용법을 이해하고 활용할 수 있도록 많이 사용해봐야할 것 같습니다.
function func() {}
var func = function () {}
(function () {})()
함수가 실행 됐을 때의 환경을 기억하는 것
함수의 인자로 함수를 전달하는 것
func.call(thisArg, ...args)
func.apply(thisArg, [...args])
func.bind(thisArg)
함수에 대해 공부하다보니 내용이 너무 많아져 챕터를 나누어 정리했습니다. 자바스크립트에서 많은 기능을 제공하지만, 그 기본이 되는 함수에 대해 자세히 알 필요성이 있다고 느끼는 시간이였습니다. 함수에 대해 정리하고 나니 뭔가 멍~해지는 기분이 듭니다.. 무의식에 사용했던 것들인데, 정확한 내용도 잘 모르고 그냥 사용했던 것에 대해 약간의(?) 후회가 듭니다. 이제 함수를 사용할 때 여러 고민을 해보고 사용할 것 같습니다. 그럼 함수에 대해서는 이만 마치도록 하겠습니다.