let keyword

ES6에 들어서 생긴 새로운 기능 중 하나는 바로 let이다.
let은 var와 같이 변수를 선언하고자 할 때 사용된다.
다만 var와는 다른 몇 가지 차이점이 존재한다.

scope

var는 선언된 함수의 전체 scope안에서 사용 가능하다. 하지만 let은 선언된 block scope {}내에서만 사용할 수 있다.
아래는 예제이다.

function test() {
  console.log('var i: %d', i);
  for (var i =0; i <10;i++) {
    console.log('i is %d', i);
  }
}
test()

위의 코드는 아래 예제를 출력한다.

var i : NaN
i is 0
i is 1
...
i is 9

하지만 let을 사용할 경우에는 달라진다.

function test() {
  console.log('let i: %d', i);
  for (let i =0; i <10;i++) {
    console.log('i is %d', i);
  }
}
test()

아래와 같은 메세지가 출력된다.

console.log('let i: %d', i);
ReferenceError: i is not defined

let은 {}안에서만 유효하여 {}밖에서 접근이 불가하지만 var는 선언된 함수 내에서 유효하므로 출력 값이 다르게 나타난다.

hoisting

var, let 모두 선언시에 자동으로 유효범위의 최상단으로 올려져 선언된다.
하지만 여기서도 차이점이 존재한다.

function foo() {
  console.log('var i is %d', i);
  var i = 0;
}

아래는 let을 사용한다.

function foo() {
  console.log('let i is %d', i);
  let i = 0;
}

var를 사용하면 NaN이 출력되지만 let은 not defined 에러를 발생시킨다.
이를 let의 temporal dead zone이라 한다.
이외에도 같은 이름의 let을 두번 호출하는 것도 temporal dead zone에 의해 에러를 발생시키다.

같은 scope내에서는 확실히 let이 덜 memory를 덜 쓰게 된다.

같은 for loop를 동일하게 돌때 비교하면 아래와 같은 결과를 보여준다.

'use strict';

let pre = process.memoryUsage();

console.log('pre', pre);

function f() {
  let obj = {x: 12};
  return obj.x;
}

function test() {
  for (let i =0;i<1000000000;i++) {
    f();
  }
  let post = process.memoryUsage();
  console.log('post', post);
}
test();
var pre = process.memoryUsage();
console.log('pre', pre);
function f() {
  var obj = {x: 12};
  return obj.x;
}
function test() {
  for (var i =0;i<1000000000;i++) {
    f();
  }
  var post = process.memoryUsage();
  console.log('post', post);
}
test();

결과는 아래와 같이 let이 덜 쓰는 것이 보이게 된다.

$ node let.js
pre { rss: 20791296, heapTotal: 9275392, heapUsed: 3567928 }
post { rss: 21594112, heapTotal: 9275392, heapUsed: 4425544 }
$ node var.js
pre { rss: 20783104, heapTotal: 9275392, heapUsed: 3567912 }
post { rss: 24322048, heapTotal: 10307328, heapUsed: 4445888 }

realjays

반박시 당신말이 맞습니다.