(흔히 밧줄이나 장비를 이용하여) 들어[끌어]올리다.

Javascript의 특징으로 함수나 변수를 말 그대로 끌어 올린다.

test();
function test() {
	console.log('hello');
}

// hello

console.log(foo);
var foo = 'world';

// undefined

Javascript의 특징인 hoisting으로 인한 문제가 발생할 수 있다.

아래와 같은 예제가 있다.

// <input type="text" id="email">
// <input type="text" id="name">
// <input type="text" id="phone">
// <div id="notice"></div>

function show(text) {
  document.getElementById('notice').innerHTML = text;
}

function set() {
  var data = [
    { id: 'email', text: 'email' },
    { id: 'name', text: 'name' },
    { id: 'phone', text: 'phone' },
  ];
  for (var i = 0; i < data.length; i++) {
    var item = data[i];
    document.getElementById(item.id).onfocus = function () {
      show(item.text);
    };
  }
}

set();

위 코드의 원하는 동작은 아래와 같다.

  1. input 영역에 focus event 발생
  2. input의 id값과 data배열의 id 값을 매칭
  3. text 값을 #notice 영역에 출력

그러나 이 코드에는 문제가 있다. 어떤 문제가 있을까? item 변수의 값이 배열의 마지막 값으로 덮어 씌워 지기 때문에 onfocus이벤트가 발생하면 항상 ‘phone’이 출력되게 된다. 왜 그럴까 javascript의 hoisting 때문이다. var는 block scope가 아닌 function scope이기 때문에 사실상 function의 최상단에 선언 되어진다. 이것이 hoisting이다. 그렇다면 해결 방법은 무엇이 있을까? 5가지 정도가 있는것 같다.

  1. 가장 간단한 방법 let을 이용

let 은 block scope 이기 때문에 for문 내에서 존재한다. 그렇기 때문이 값이 덮어 쓰일 걱정이 없다.

function show(text) {
  document.getElementById('notice').innerHTML = text;
}

function set() {
  var a = [
    {id: 'email', text: 'email'},
    {id: 'name', text: 'name'},
    {id: 'phone', text: 'phone'},
  ];
  for (var i = 0; i < a.length; i++) {
      let item = a[i];
      document.getElementById(item.id).onfocus = function() {
        show(item.text);
      };
  }
}

set();
  1. closure 함수를 이용한 방법