Scenario


최근에 es6로 프로그래밍을 하면서, let을 많이쓰게되었고, let은 단순히 지역변수라고만 생각했엇다.

근데 다시 곰곰히 생각해보니 var도 function scope 이므로 지역변수로 사용할 수 있지않은가?

라는 생각이 들었다. 책에서 읽었던 내용중에 let은 bracket scope 였던게 생각이났다.

function run() {
  var foo = "Foo";
  let bar = "Bar";

  console.log(foo, bar);

  {
    let baz = "Bazz";
    console.log(baz);
  } //사실 braket scope을 그닥 많이쓰진 않는다.

  console.log(baz); // ReferenceError
} 

run();

 사실 나의경우는 component 기반 es6 기반 프레임워크&라이브러리로 javscript를 쓰다보면 bracket scope을 그닥 많이 쓰진않는다. 그럼 let이라는게 왜 등장을 한지 배경을 좀 조사해보았다.

 

var funcs = [];

for (var i = 0; i < 3; i++) {
  // and store them in funcs
  funcs[i] = function() {
    // each should log its value.
    console.log("My value: " + i);
  };
}
for (var j = 0; j < 3; j++) {
  funcs[j]();
}
//output: expect 0, 1, 2 but
//My value: 3
//My value: 3
//My value: 3

위 예제의 경우 let을 써야하는 이유가 더 와닿는다. (실제로도 나는 let은 for문에서 가장많이쓰는것같다.)

 

Solution


먼저 var로 선언된 변수를 이해 하려면, hoisting을 이해해야 한다. 

 

hoisting 


사전적의미로 들어올리다 이다. 자바스크립트의 hoisting을 이해하려면 다음 소스코드부터 보자.

 

function run() {
  console.log(foo); // undefined -- ReferenceError가 나지않는다.
  var foo = "Foo";
  console.log(foo); // Foo
}

run();

 

 위 소스코드에서 3번째 줄에서 오류가 나지않는 이유는 hoisting 되었기 때문이다. 변수가 생성된 시점은 3번째줄이지만,  scope 상단으로 hosting 되어진다. 이는 변수들이 선언되기 전에 스코프내에서 접근할 수 있다는 것을 의미한다.
(var는 초기화 되기 전까지는 블록의 시작에 "temporal dead zone"에 있다고들 말한다.)  

 

function checkHoisting() {
  console.log(foo); // ReferenceError
  let foo = "Foo";
  console.log(foo); // Foo
}

checkHoisting();

그러나 위의 소스코드는 error가 난다. 이유는 let은 호이스팅 되지 않기 때문에 선언되기 전에 foo에 접근을 시도하기 때문이다. 이는 아주 중요한 차이점을 갖는다.

 

주의점

gloval scope에선 let을 쓰지 않도록 주의해야한다.

var foo = "Foo";  // globally scoped
let bar = "Bar"; // globally scoped

console.log(window.foo); // Foo
console.log(window.bar); // undefined

 

또한 var는 재정의할 수있으므로 주의해서 써야한다.

var foo = "foo1";
var foo = "foo2"; // No problem, 'foo' is replaced.

let bar = "bar1";
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared

 

 

그리고 아까위의 for문은 다음과 같이 고칠 수 있다.

var funcs = [];
// let's create 3 functions
for (let i = 0; i < 3; i++) {
  // and store them in funcs
  funcs[i] = function() {
    // each should log its value.
    console.log("My value: " + i);
  };
}
for (var j = 0; j < 3; j++) {
  // and now let's run each one to see
  funcs[j]();
}
//output
//My value: 0
//My value: 1
//My value: 2

 

*주의 : ie에서는 let을 지원하지않으므로, webpack과 같은 bundle을 쓰지않는다면 쓰지말자.

 

+ Recent posts