| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
- axios
- freecodecamp
- 힘들었던 한주
- git flow start
- git flow finish
- 공부할 거 넘많다~
- 바닐라JS
- AJAX
- fetch pull 차이
- Next.js
- 끝까지 잘 마무리하기
- HTML
- 책으론 원리만
- Main
- Mac
- api 라우트
- jQuery
- 실무는 공식문서로
- js
- 서버 컴포넌트
- 개발일지
- 클라이언트 컴포넌트
- 다시 홧팅
- git
- CSS
- JavaScript
- javascript30
- 백준
- 차이점
- TS
- Today
- Total
다다의 개발일지 6v6
[JS] 함수 호이스팅에 대해서도 알아보자. + 함수 선언문, 함수 표현식, 화살표 함수, 함수에서의 this 본문
[JS] 함수 호이스팅에 대해서도 알아보자. + 함수 선언문, 함수 표현식, 화살표 함수, 함수에서의 this
dev6v6 2025. 2. 21. 16:58전 글에서 호이스팅에 대해서 공부를 했는데 변수 호이스팅만 다루고 함수 호이스팅은 따로 빼놨다.
함수 호이스팅에 대해서 자세히 알아보자!!
함수 호이스팅이란?
JavaScript 엔진이 함수 선언을 코드 실행 전에 메모리에 미리 저장하는 동작을 의미
즉, 코드가 작성된 순서와는 다르게, 함수의 선언이 코드의 최상단으로 끌어올려지는 것처럼 동작한다.
하지만 실제로 코드의 위치가 변경되는 것이 아니라, JavaScript가 내부적으로 선언을 미리 처리하는 것임.
함수도 호이스팅되지만, 함수 선언 방식에 따라 다르게 동작한다.
(1) 함수 선언문 (Function Declaration)
👉 function 키워드로 직접 함수를 선언하는 방식
hello(); // "Hello, world!" (정상 작동)
function hello() {
console.log("Hello, world!");
}
✅ 함수 선언문(function name() {})은 전체가 호이스팅되므로 호출이 정상적으로 작동함
✅ 호이스팅 될 때 함수 전체가 메모리에 올라간다.
(2) 함수 표현식 (Function Expression)
👉 함수를 변수에 할당하는 방식
greet(); // TypeError: greet is not a function
var greet = function() {
console.log("Hi!");
};
호이스팅 후 실행 과정:
var greet; // 변수 선언만 호이스팅됨 (초기화 X)
greet(); // TypeError (greet는 아직 함수가 아니라 undefined)
greet = function() {
console.log("Hi!");
};
✅ 함수 표현식은 var처럼 호이스팅 시 변수 선언만 되고, 함수 할당은 나중에 이루어짐
✅ 따라서 greet는 undefined이므로 greet()을 실행하면 오류 발생
(3) let, const을 사용한 함수 표현식
sayHi(); // ReferenceError (TDZ로 인해 접근 불가)
let sayHi = function() {
console.log("Hi!");
};
✅ let과 const는 TDZ가 적용되므로 선언 전에 접근하면 오류 발생
✅ var보다 안전하므로 함수 표현식에는 const 또는 let을 사용하는 것이 좋음
(4) 화살표 함수 (Arrow Function)
👉 함수 표현식과 같은 방식이지만, this 바인딩이 다름.
const hello = () => {
console.log("Hello, world!");
};
hello(); // ✅ 정상 작동
✅ 화살표 함수는 함수 표현식처럼 동작하고, this가 다르게 동작하는 특징이 있음.
▼ 함수 선언문 vs 함수 표현식 vs 화살표 함수에서 this의 차이
자바스크립트에서 this는 함수를 호출하는 방식에 따라 달라지는 동적 바인딩(Dynamic Binding)을 가진다.
특히, 화살표 함수는 기존 함수와 this 동작이 다르므로 조심해야 한다.
1. 일반 함수 (this가 호출 방식에 따라 달라짐)
(1) 일반 함수 (함수 선언문, 함수 표현식) 에서 this
👉 this는 기본적으로 "전역 객체"(window 또는 globalThis)를 가리킴.
👉 객체(obj)의 메서드(method 함수)로 호출하면 해당 객체(obj)를 가리킴.
- 객체에서 value가 함수인 프로퍼티(key)는 메서드라고 불린다.
- 메서드는 객체 내부에서 객체의 데이터를 다루는 함수로 동작한다.
- 메서드는 객체의 데이터를 읽거나 수정할 수 있는 기능을 수행하는 데 유용하다
function normalFunction() {
console.log(this);
}
const obj = {
method: function() {
console.log(this);
}
};
normalFunction(); // 브라우저: `window`, Node.js: `globalThis`
obj.method(); // `obj` 객체 (메서드를 호출한 객체)
✅ 전역 함수로 호출하면 this는 window (브라우저) 또는 globalThis (Node.js).
✅ 객체의 메서드로 호출하면 this는 해당 객체를 가리킴.
+ 객체에서 함수가 메서드로 동작하는 방식
const person = {
name: "Alice",
greet: function() {
console.log("Hello, " + this.name);
}
};
person.greet(); // "Hello, Alice"
이 예시에서 person 객체는 두 개의 프로퍼티가 있는데:
- name은 값이 "Alice"인 프로퍼티
- greet는 값이 함수인 프로퍼티로, 이 함수는 객체의 "메서드"라고 부를 수 있다.
객체 메서드의 다른 표현
1. 기존 함수 표현식 방식
const person = {
name: "Alice",
greet: function() {
console.log("Hello, " + this.name);
}
};
2. ES6 축약 문법 (메서드 축약 방식)
const person = {
name: "Alice",
greet() {
console.log("Hello, " + this.name);
}
};
이렇게 작성해도 greet는 여전히 메서드로 간주된다.
(2) this가 동적으로 바뀌는 예시
const obj = {
name: "Alice",
sayHello: function() {
console.log(this.name);
}
};
const say = obj.sayHello; // 메서드를 변수에 저장
say(); // ❌ undefined (전역 호출 → `this`가 `window`가 됨)
obj.sayHello(); // ✅ "Alice" (obj의 메서드를 호출 → `this`가 `obj`)
🚨 sayHello를 객체에서 분리해서 호출하면 this가 window를 가리켜서 undefined가 나옴.
2. 화살표 함수에서 this (Lexical this)
👉 화살표 함수는 this를 자신을 감싸는 "외부 함수(스코프)"의 this를 상속받음.
👉 즉, this가 window나 globalThis로 바뀌지 않고, 원래의 this를 유지함!
const obj = {
name: "Alice",
sayHello: () => {
console.log(this.name);
}
};
obj.sayHello(); // ❌ undefined (화살표 함수의 `this`는 `obj`가 아니라 `window`!)
🚨 화살표 함수는 this를 바인딩하지 않고, 외부 스코프(window)를 따른다!
(1) 화살표 함수 내부에서 this 유지
const obj = {
name: "Alice",
sayHello: function() {
const inner = () => {
console.log(this.name);
};
inner(); // ✅ "Alice" (화살표 함수가 외부 `this`를 유지)
}
};
obj.sayHello(); // ✅ "Alice"
✅ 화살표 함수는 this를 새로 정의하지 않고, sayHello의 this(obj)를 유지함.
setTimeout에서 this 차이 (일반 함수, 화살표 함수)
const obj = {
name: "Alice",
sayHello: function() {
setTimeout(function() {
console.log(this.name);
}, 1000);
}
};
obj.sayHello(); // ❌ undefined (setTimeout의 `this`는 `window`)
🚨 setTimeout 내부의 일반 함수는 this가 window를 가리키므로 undefined가 출력됨.
이때, 화살표 함수를 사용하면 해결됨!
const obj = {
name: "Alice",
sayHello: function() {
setTimeout(() => {
console.log(this.name);
}, 1000);
}
};
obj.sayHello(); // ✅ "Alice" (화살표 함수는 `this`를 유지!)
✅ 화살표 함수는 this를 바꾸지 않고, sayHello의 this(obj)를 그대로 사용함.
이때 !! 콜백함수를 function안에 넣지 않고 쓰면 sayHello는 메서드의 역할을 하지 못함.
즉, 콜백함수를 메서드 안에서 사용하려면
setTimeout을 메서드 안에서 사용하려면, greet을 일반 함수로 정의해야 하며, setTimeout의 콜백 안에서 화살표 함수를 사용하여 this를 외부 함수의 this로 유지해야 한다.
this 차이 정리 (표)
| 일반 함수 (function) | 화살표 함수 (=>) | |
| 기본 this | 호출 방식에 따라 달라짐 | 새로 바인딩x -> 선언된 위치의 this를 유지 |
| 전역에서 호출 | window (브라우저) / globalThis (Node.js) | window / globalThis 유지 |
| 객체의 메서드 | 메서드를 호출한 객체 | this는 객체를 가리키지 않음 (window) |
| 메서드 내부 함수 | window (전역 객체) | 외부 this를 유지 |
| setTimeout 내부 | window (전역 객체) | 외부 this를 유지 |
- 객체의 메서드를 사용할 때는 화살표 함수 사용에 주의해야 함.
- 콜백 함수(setTimeout 등)에서는 화살표 함수가 유용함.
정리
| 호이스팅 | 선언 전 접근 | |
| 함수 선언문 | O (전체) | 정상 실행 가능 |
| 함수 표현식, 화살표 함수 (var) | O (변수 선언만) | TypeError (undefined라서 실행 불가) |
| 함수 표현식, 화살표 함수 (let, const) | O (TDZ 있음) | ReferenceError (접근 불가) |
✔ 함수 선언문은 호이스팅되므로 선언 전에 호출해도 문제없음 -> 호이스팅이 중요한 경우 사용
✔ 함수 표현식은 변수 호이스팅의 영향을 받으므로 선언 전에 호출하면 오류 발생
✔ 안전한 코드를 위해 const 또는 let을 사용하고, 함수 표현식보다는 함수 선언문을 적절히 활용하자!
✔ 변수처럼 다룰 필요가 있다면 함수 표현식을 사용하면 좋다.
✔ 화살표 함수는 함수 표현식과 비슷하지만 this 동작이 다름.
'Frontend > JavaScript' 카테고리의 다른 글
| jQuery - HTML 요소들을 조작하는 편리한 JS 라이브러리 (레거시) (0) | 2025.02.24 |
|---|---|
| Ajax - JS에서 클라이언트와 서버의 '비동기적' API 통신 방식 + jQuery, fetch API, Axios, SSE, WebSockets (0) | 2025.02.24 |
| [JS] var, let, const의 차이점 + 변수호이스팅 , 스코프 (0) | 2025.02.21 |
| [JS] Day 3 - CSS Variables ( JS로 CSS 변수 수정하기! ) (0) | 2025.02.21 |
| [JS] day2 - JS and CSS Clock ( 돌아가는 시계 만들기 ) (0) | 2025.02.19 |