자바스크립트 JS - 변수 (Variable) & 호이스팅 (hoisting)

hyunnu·2021년 3월 31일
0
post-thumbnail

📖 Review (21.03.31)

변수 (Variable)

원시 타입 (primitive data type):

boolean, string, number

undefiend : 변수는 존재하나, 어떠한 값으로도 할당되지 않아 자료형이 정해지지(undefined) 않은 상태입니다.

null : 변수는 존재하나, null 로 (값이) 할당된 상태. 즉 null은 자료형이 정해진(defined) 상태입니다.

symbol : 심볼은 객체 속성(object property)을 만들 수 있는 원시 데이터 형식(primitive data type) 이다. 정의하면 독립적인 값이 되기때문에, 같은 string 으로 정의해도 같은 값이 아니다.

객체 타입 (object/ reference type)

object

let , const , var 의 차이

  • letconstblock-scoped이고 varfunction-scoped이다.

  • letconst는 재선언이 불가능하다.

  • letconst의 차이점은 변수의 immutable 여부이다.
    let은 변수에 재할당이 가능하지만, const는 변수 재선언, 재할당이 모두 불가능하다.

    #What is function-scoped & block-scoped ?

    function-scoped

    1. 일반 함수에서 선언된 var는 그 함수의 코드블록 전체가 스코프이다. 전역함수에서 생성된 변수는 모두 전역 변수이다.
    2. for문의 변수 선언문에서 선언한 변수를 for문의 코드블록 외부에서 참조할수 있다.
    console.log(i) //undefined..정의는 되어있지만 값만 없는 상태
    for(var i = 0; i < 10; i++){
    }
    console.log(i) //10
    1. var는 변수 선언(var i)과 초기화(i = undefined)가 한번에 이루어진다.

    block-scoped

    console.log(i) //error . i is not defined
    for(let i = 0; i < 10; i++){
    }
    console.log(i) //error i is not defined
    1. ivar로 선언하게 되면, 끌어올림이 발생하여 할당(assign)을 하지 않아도 정의가 되어있습니다.
    2. letconst같은 block-scoped는 선언을 하고 자신의 유효범위(해당 블록)안에서만 쓸 수 있습니다. 지역변수와 같은 개념입니다.

호이스팅 (Hoisting)

var의 hoisting

// var는 function-scope이기 때문에 for문이 끝난다음에 j를 호출하면 값이 출력이 잘 된다.
// 이건 var가 hoisting이 되었기 때문이다.
for(var j=0; j<10; j++) {
  console.log('j', j)
}
console.log('after loop j is ', j) // after loop j is 10


아래의 경우에는 에러가 발생한다.
```java
function counter () {
  for(var i=0; i<10; i++) {
    console.log('i', i)
  }
}
counter()
console.log('after loop i is', i) // ReferenceError: i is not defined

javascript에서는 immediately-invoked function expression (or IIFE, pronounced "iffy")라는것이 있다.
IIFEfunction-scoped인거 처럼 만들 수가 있다.

// IIFE를 사용하면
// i is not defined가 뜬다.
(function() {
  // var 변수는 여기까지 hoisting이 된다.
  for(var i=0; i<10; i++) {
    console.log('i', i)
  }
})()
console.log('after loop i is', i) // ReferenceError: i is not defined

위에서 잠깐 말했지만 IIFEfunction-scoped처럼 보이게 만들어주지만 결과가 같지는 않다.

// 이 코드를 실행하면 에러없이 after loop i is 10이 호출된다.
(function() {
  for(i=0; i<10; i++) {
    console.log('i', i)
  }
})()
console.log('after loop i is', i) // after loop i is 10

위에 코드가 아무 에러 없이 실행되는 이유는 i가 hoisting이 되어서 global variable이 되었기 때문이다.

그래서 아래와 같이 된 것이다.

var i
(function() {
  for(i=0; i<10; i++) {
    console.log('i', i)
  }
})()
console.log('after loop i is', i) // after loop i is 10

IIFE는 쓰는데 이렇게 hoisting이 된다면 무슨 소용이 있겠는가?!

그래서 이런 hoisting을 막기 위해 use strict를 사용한다.

// 아까랑 다르게 실행하면 i is not defined라는 에러가 발생한다.
(function() {
  'use strict'
  for(i=0; i<10; i++) {
    console.log('i', i)
  }
})()
console.log('after loop i is', i) // ReferenceError: i is not defined

let , const의 hoisting

let, const가 hoisting이 발생하지 않는건 아니다.

varfunction-scoped로 hoisting이 되었다면

let, constblock-scoped단위로 hoisting이 일어나는데

c = 'test' // ReferenceError: c is not defined
let c

위에 코드에서 ReferenceError가 발생한 이유는 tdz(temporal dead zone)때문이다.

let은 값을 할당하기전에 변수가 선언 되어있어야 하는데 그렇지 않기 때문에 에러가 난다.

이건 const도 마찬가지인데 좀 더 엄격하다.

// let은 선언하고 나중에 값을 할당이 가능하지만
let dd
dd = 'test'

// const 선언과 동시에 값을 할당 해야한다.
const aa // Missing initializer in const declaration
profile
Data Engineer / Back-End Developer

0개의 댓글