0. 함수
0-0) 함수 리터럴
- 자바스크립트 함수는 객체 타입의 값이다.
- 따라서 숫자값을 숫자리터럴로 생성하고 객체를 객체리터럴로 생성하는것처럼 함수도 함수리터럴로 생성가능하다.
- 함수 리터럴은 function 키워드, 함수 이름, 매개변수 목록, 함수 몸체로 구성된다.
- 함수 이름은 함수 몸체 내에서만 참조가능한 식별자다.
- 함수 이름이 있는 함수를 기명함수(named function)라 하고, 이름이 없는 함수를 무명/익명 함수(anonymous function)라고 한다.
ex) 함수리터럴 생성 예제
// 변수에 함수리터럴 할당
var f = function add(x, y) {
return x + y;
};
- 리터럴은 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기방식을 말한다.
- 즉, 리터럴은 값을 생성하기 위한 표기법이다.
따라서 함수 리터럴도 평가되어 값을 생성하며, 이 값은 객체다 -> 함수는 객체!
함수는 객체지만 일반 객체와는 다르다.
일반 객체는 호출할 수 없지만 함수는 호출할 수 있다.
그리고 함수는 일반객체에는 없는 함수 객체만의 고유한 프로퍼티를 갖는다.
함수가 객체라는 사실은 다른 프로그래밍언어와 구별되는 자바스크립트의 고유한 특징이다.
0-1) 함수를 정의하는 다양한 방법
- 함수 정의란 함수를 호출하기 이전에 인수를 전달받은 매개변수와 실행할 문들, 그리고 반환할 값을 지정하는 것을 말한다.
- 정의된 함수는 자바스크립트 엔진에 의해 평가되어 함수 객체가 된다.
1️⃣함수 선언문 :
function 키워드로 선언한다. 사용하려면 해당함수 이름을 호출해야한다.
함수 선언문은 함수 리터럴과 형태가 동일하다.
단, 함수 리터럴은 함수 이름을 생략할 수 있지만 함수 선언문은 함수 이름을 생략할 수 없다.
function greet(name) {
// 함수 내부에서 수행할 작업
// 반환문을 통해 반환할 수도 있음
console.log("안녕하세요, " + name + "님!");
}
// 함수 호출
greet("John"); // 출력: 안녕하세요, John님!
함수는 어떤 작업을 내부에서 수행한 후에 결과값을 반환 할 수도 있다. return 키워드를 사용하여 함수 내부에서 결과값을 반환할 수 있다.
function addNumbers(a, b) {
return a + b;
}
// 함수 호출 및 반환 값 사용
var result = addNumbers(3, 4);
console.log(result); // 출력: 7
2️⃣함수표현식
변수로 저장이 가능하다. 변수에 저장되면 변수는 함수처럼 사용 가능해진다. 변수에 저장된 함수는 함수명이 필요없으며, 변수 이름을 통하여 호출된다.
var add = function(x,y){
return x + y;
}
add(3,4) // 7
+) 함수 표현식의 장점
1. 콜백으로 사용할 수 있다. (함수 표현식을 다른 함수의 인자 값으로 넘길 수 있다. )
var msg = function () {
console.log('Hello World');
}
$(document).ready(msg);
2. 클로저로 사용 (추후 내용 추가 예정)
3️⃣생성자함수
내장 생성자 함수인 'Function'을 사용하여 동적으로 함수를 생성하는 방법
'new Function'을 사용하면 실행 중에 문자열 형태로 작성된 자바스크립트 코드를 함수로 변환할 수 있다.
var add = new Function('x','y', 'return x+y');
var addNumbers = new Function("a", "b", "return a + b;");
// 함수 호출
var result = addNumbers(3, 4);
console.log(result); // 출력: 7
4️⃣ 화살표 함수
var add = (x,y) => x+y;
🔸함수 선언문과 함수 표현식의 호이스팅
※ 호이스팅 : 자바스크립트 엔진이 코드를 해석하는 과정에서 변수 및 함수 선언을 끌어올리는 것.
함수 선언문은 호이스팅에 영향을 받지만, 함수 표현식은 호이스팅에 영향을 받지 않는다. (물론 둘다 호이스팅이 됨)
1) 함수 선언문은 함수 선언 전에 함수를 사용할 수 있다. '호이스팅' 에 영향을 받는다.
자바스크립트 엔진이 study 함수의 선언과 동시에 완성된 함수 객체를 생성해서 환경 레코드에 기록해둔다. study() 함수를 실행하면 에러없이 실행된다.
함수 선언문으로 선언한 함수는 선언한 동시에 함수가 생성되어 선언전에도 함수를 사용할 수 있다.(따라서, 사용을 지양하고자 하는 목소리도 있음)
2) 함수 표현식에서 변수 호이스팅과 동일하게 작동한다. 즉, 변수는 선언부와 할당부를 나누어 호이스팅 하게 된다.
변수 선언이 호이스팅 되지만 초기값이 할당되지 않았기 때문에 addNumbers는 undefined가 출력.
함수 표현식은 변수에 할당된 이후부터 호출이 가능합니다. 호이스팅은 변수 선언 자체를 끌어올리지만, 할당 부분은 그대로 실행 흐름에 따라 진행됩니다.
즉, 함수 표현식을 할당하는 변수는 호이스팅이 되지만, 함수 표현식 자체는 호이스팅되지 않는다.
var 키워드로 작성한 함수 표현식은 선언과 초기화가 동시에 이루어지기에 undefined가 출력이된다.
console.log(addNumbers); // 출력: undefined
var addNumbers = function(a, b) {
return a + b;
};
console.log(addNumbers(3, 4)); // 출력: 7
같은 함수를 const 키워드로 작성했을 때는 변수 선언이 호이스팅이 되지만, 초기화가 되지 않아서 변수가 선언되기 전에 접근하면 참조 오류가 발생한다.
console.log(addNumbers); // 출력: Uncaught ReferenceError
const addNumbers = function(a, b) {
return a + b;
};
아래 예제와 같이 var 키워드에 함수를 담아 선언문 이전에 실행하려고 하면, 환경레코드에 undefined가 기록되고, undefined라는 데이터타입은 함수와 달리 호출될 수 없기 때문에 타입에러가 발생한다.
즉, 변수 할당 이전에 함수를 호출하려고 해서 TypeError가 발생한다. 함수 표현식의 경우 변수 할당 이후에 함수가 호출될 수 있다. 선언부만 호이스팅 하게 되므로 Type Error가 된다.
+) 더 구체적인 예제
// 실행 전
logMessage();
sumNumbers();
function logMessage() {
return 'worked';
}
var sumNumbers = function () {
return 10 + 20;
};
호이스팅에 의해 자바스크립트 해석기는 코드를 아래와 같이 인식한다.
// 실행 시
function logMessage() {
return 'worked';
}
var sumNumbers;
logMessage(); // 'worked'
sumNumbers(); // Uncaught TypeError: sumNumbers is not a function
sumNumbers = function () {
return 10 + 20;
};
함수 표현식 sumNumbers 에서 var 도 호이스팅이 적용되어 위치가 상단으로 끌어올려졌다.
하지만 실제 sumNumbers 에 할당될 function 로직은 호출된 이후에 선언되므로, sumNumbers 는 함수로 인식하지 않고 변수로 인식한다.
var sumNumbers;
logMessage();
sumNumbers();
1. 즉시 실행 함수
함수 정의와 동시에 즉시 호출되는 함수를 즉시 실행 함수 (IIFE, Immediately Invoked Function Expression) 라고 한다. 즉시 실행 함수는 단 한 번만 호출되며 다시 호출할 수 없다.(일회성 작업)
소괄호로 감싸서 실행하는 문법을 사용한다. 선언과 동시에 출력한다.
(function () {
console.log("IIFE");
})(); //IIFE
즉시 실행 함수는 함수 이름이 없는 익명 함수를 사용하는 것이 일반적이다.
//익명 즉시 실행함수
(function () {
var a = 3;
var b = 5;
return a * b;
})();
함수 이름이 있는 기명 즉시 실행 함수도 사용할 수 있다. 하지만 즉시실행함수는 선언과 동시에 호출되어 반환되어 재사용 할 수 없기 때문에 이름을 지어주는 것이 의미가 없다.
//기명 즉시 실행 함수
(function foo() {
var a = 3;
var b = 5;
return a * b;
})();
foo(); //ReferenceError: foo is not defined
즉시 실행 함수는 반드시 그룹 연산자 (...)로 감싸야 한다.
function () {
//SyntaxError: Function statements require a function name
...
}
함수 정의가 함수 선언문의 형식에 맞지 않기 때문이다. > 그룹 연산자로 함수를 묶은 이유는 먼저 함수 리터럴을 평가해서 함수 객체를 생성하기 위해서다
+) 즉시 실행 함수는 언제 사용할까?
1. 필요없는 전역 변수의 생성을 줄일 수 있다.
함수를 생성하면 그 함수는 전역 변수로써 남아있게 되고, 많은 변수의 생성은 전역 스코프를 오염시킬 수 있다.
즉시실행함수를 선언하면 전역으로 저장되지 않기 때문에 전역 스코프의 오염을 줄일 수 있다.
(function () {
test1();
test2();
})();
이런 식으로 사용할 경우 이 함수는 딱 여기서만 사용가능하게 되는 것이다. 다른 곳에서는 이 함수를 사용할 수 없게 된다. 즉시실행함수가 필요한 이유는 딱 여기서만 이 함수를 사용하고 다른 코드에서는 이 함수를 사용하지 못하게 하는 의미가 있다.
만약 아래와 같이 사용한다면, javascript 어느 파일에서나 이 함수를 호출할 수 있게 됩니다. 어디서 어떻게 이 함수를 호출했는지 찾기 힘들게 된다는 것이다.
function temp() {
test1();
test2();
}
temp();
참고자료
https://github.com/junh0328/prepare_frontend_interview/blob/main/js.md#%ED%95%A8%EC%88%98
https://jongminfire.dev/java-script-%EC%A6%89%EC%8B%9C%EC%8B%A4%ED%96%89%ED%95%A8%EC%88%98-iife
'프론트엔드 개발 > JavaScript' 카테고리의 다른 글
자바스크립트) 실행컨텍스트, 호이스팅, 렉시컬환경, 스코프체인 (1) | 2023.06.04 |
---|---|
자바스크립트) 스코프 (0) | 2023.06.01 |
자바스크립트) 객체 (0) | 2023.05.28 |
자바스크립트) 배열 (0) | 2023.05.28 |
자바스크립트) 자주 쓰이는 메서드 총정리 (0) | 2023.05.17 |