자바스크립트/Likelion_JS

2-6. Scope 와 Hoisting

김딸기* 2024. 10. 5. 02:03

함수와호이스팅

호이스팅(Hoisting)은 자바스크립트에서 나중에 선언된 변수나 함수를 코드 맨 위로 끌어올려 먼저 사용할 수 있게 해주는 기능입니다.

 

변수 호이스팅: 변수를 코드 아래에서 선언해도, 자바스크립트가 그 변수를 코드 맨 위로 끌어올려 오류 없이 사용할 수 있게 해주는 기능입니다. var로 선언한 변수만 호이스팅되며, 값이 할당되기 전까지는 undefined 상태입니다.         

=> let, const 로 선언된 변수는 호이스팅이 지원되지않습니다

//var hoisting test......................
//아래에 선언된 변수의 선언부분만(값 할당은 빼고) 위로 올린다.
console.log(`step1, data1 = ${data1}`)//step1, data1 = undefined
data1 = 20
console.log(`step2, data1 = ${data1}`)//step2, data1 = 20
var data1 = 10
console.log(`step3, data1 = ${data1}`)//step3, data1 = 10

//test2................let, const hoisting............
console.log(data2)//Cannot access 'data2' before initialization
console.log(data3)//Cannot access 'data3' before initialization
let data2 = 10
const data3 = 30

//==>var 에 한해서만 hoisting 에 의해 선언위치 위에서 변수 이용 가능

 

 

함수 호이스팅: 함수도 코드 아래에 선언된 함수를 위에서 사용할 수 있게 해주는 기능입니다. 다만, 함수 선언식만 호이스팅되고, 함수 표현식은 호이스팅되지 않습니다.

//test3.........함수 호이스팅................
console.log(myFun1())//myFun1 call
function myFun1(){
  return 'myFun1 call'
}

 console.log(myFun2())//error... Cannot access 'myFun2' before initialization
const myFun2 = () => {
  return 'myFun2 call'
}

이처럼, 코드 실행 전에 변수와 함수가 자동으로 위로 올라가는 것을 호이스팅이라고 합니다.


1. 함수 선언식 (Function Declaration)

  • 정의: 함수 이름과 함께 정의하는 방법입니다.
  • 호이스팅: 이 방식으로 정의된 함수는 코드 어디에서든 호출할 수 있습니다.
    //함수선언식
    console.log(add(2, 3)); // 5 (호출하기 전에 정의해도 됨)

    function add(a, b) {
        return a + b; // 두 수를 더해서 반환
    }

2. 함수 표현식 (Function Expression)

  • 정의: 변수를 사용해 함수를 정의하는 방법입니다. 보통 이름이 없습니다(익명 함수).
  • 호이스팅: 이 방식으로 정의한 함수는 정의하기 전에 호출할 수 없습니다.
    console.log(multiply(2, 3)); // 에러 발생 (호출하기 전에 정의해야 함)

    //함수표현식->변수로 표현
    const multiply = function(a, b) {
        return a * b; // 두 수를 곱해서 반환
    };

요약

  • 함수 선언식: 쉽게 정의하고, 어디서든 호출 가능.=>호이스팅 가능
  • 함수 표현식: 변수를 사용해 정의하고, 정의한 후에만 호출 가능.

스코프

코드는 {}로 묶여 같은 영역에서 실행되며, 이를 스코프라고 합니다.

  1. 스코프코드가 실행되는 범위를 의미합니다. {}로 묶인 함수, for문, if문 등이 스코프를 형성합니다. 그 안에서 선언된 변수는 그 스코프 안에서만 유효합니다.
  2. 중복 선언은 같은 이름의 변수를 다시 선언하는 것을 말합니다.
    • 다른 스코프에서는 같은 이름의 변수를 선언해도 서로 영향을 주지 않으므로 문제가 되지 않습니다.
    • 하지만 같은 스코프에서 중복 선언할 경우, var로 선언된 변수는 허용되지만, let과 const로 선언된 변수는 중복이 불가능합니다.
  3. var는 함수 스코프만 지원하며, for문이나 if문 같은 블록 스코프에서는 영향을 받지 않습니다.

var 변수함수 안에서만 사용되고, 블록 {}에서는 유효 범위가 아니라, 전체 함수에서 접근할 수 있어요.
다른 방법인 let이나 const는 블록 안에서만 사용 가능하답니다.

함수 스코프: 함수 내에서만 유효하며, 함수 밖에서는 접근 불가능. (var로 선언한 변수)
블록 스코프: 블록 {} 내에서만 유효하며, 블록 밖에서는 접근 불가능. (let이나 const로 선언한 변수)

결론적으로, 변수 선언 시 스코프를 잘 이해하고 var, let, const를 적절히 사용해야 합니다.

//함수 중복 선언................................
function myFun1(){ console.log('step1') }  // 선언식 함수
function myFun1(){ console.log('step2') }
myFun1()//step2

var myFun2 = function(){console.log('step1')} //  var 에 대입되는 표현식 함수
var myFun2 = function(){console.log('step2')}
myFun2()//step2

let myFun3 = function(){console.log('step1')}
let myFun3 = function(){console.log('step2')}//error

//==>함수 중복 선언 : 선언식 함수와 var 에 대입되는 표현식 함수만

var과 스코프

  • var: var로 선언한 변수는 함수 안에서 선언하면 그 함수 스코프 내에서만 사용할 수 있습니다. 만약 함수 밖에서 var로 변수를 선언하면, 그 변수는 전역 변수(Global Variable)가 되어 전체 코드에서 사용할 수 있습니다.
function myFunction() {
    var functionScoped = "나는 함수 스코프 안에 있어요!";
    console.log(functionScoped); // "나는 함수 스코프 안에 있어요!" 출력
}

myFunction();

console.log(functionScoped); // 오류 발생! 함수 밖에서는 사용할 수 없습니다.
  • 블록 스코프: let이나 const로 선언한 변수는 블록 {} 안에서만 사용할 수 있습니다. 블록 밖에서는 접근할 수 없습니다.

블록 스코프 예시

{
    let blockScoped = "나는 블록 스코프 안에 있어요!";
    console.log(blockScoped); // "나는 블록 스코프 안에 있어요!" 출력
}

console.log(blockScoped); // 오류 발생! 블록 밖에서는 사용할 수 없습니다.

요약

  • var로 선언한 변수:
    • 함수 안에서 선언하면 함수 스코프 안에서만 유효합니다.
    • 함수 밖에서 선언하면 전체 코드에서 유효하게 됩니다 (전역 변수).
  • let과 const로 선언한 변수:
    • 블록 {} 안에서만 유효하고, 블록 밖에서는 사용할 수 없습니다.


let name1 = '홍길동'

const someFun = () => {
  let name1 = '김길동'
  console.log(`in someFun 1, name1 = ${name1}`)//김
  for(let i=0; i<1; i++){
    let name1 = '이길동'
    console.log(`in someFun, in for, name1 = ${name1}`)//이
  }
  console.log(`in someFun 2, name1 = ${name1}`)//김
  if(true){
    let name1 = '박길동'
    console.log(`in someFun, in if, name1 = ${name1}`)//박
  }
  console.log(`in someFun 3, name1 = ${name1}`)//김
}
someFun()
console.log(`out someFun, name1 = ${name1}`)//홍
// in someFun 1, name1 = 김길동
// in someFun, in for, name1 = 이길동
// in someFun 2, name1 = 김길동
// in someFun, in if, name1 = 박길동
// in someFun 3, name1 = 김길동
// out someFun, name1 = 홍길동

//==>let 은 함수, for, if 스코프 지원한다.