๊ณต๋ถ๋นผ๊ณ ๋ชจ๋ ๊ฒ์ด ์ฌ๋ฐ์ด์ง๋ค๋ ์ํ๊ธฐ๊ฐ์ ํน์ฑ์ ์ ๊ทน ํ์ฉํด์ ์ด๊ณณ์ CSS ๋ ๊ณ ์น๊ณ , ๊ทธ ๊ธฐ๋ ์ผ๋ก ์๋ก ํฌ์คํ ์ ํ๊ธฐ๋ก ํ๋ค. ๋ญ๊ฐ ์ค๋ฆฌ์ง๋ ํ๋ฉด์ ์์๊ฐ๊ฐ ์๊ธฐ๊ฐ ํ๋ค์ด์ ๊ณต๋ถ๋ ํ ๊ฒธ ๋ฒ์ญ ํฌ์คํ ์ ์๋ ํด๋ณด์๋ค. ์ค๋ ๋ฒ์ญํ ํ ์คํธ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ฐ๊ตฌ๊ฐ์ด์ Axel Rauschmayer๋์ด ์ด Exploring ES6๋ผ๋ online book ์ 9 ๋ฒ์งธ ๋จ์์ด๋ค. ์~์ ์ ํน์ ๋ถ๋ถ๋ถ๋ถ ๋ฒ์ญํด๋ ๋๋๊ณ ๋ฉ์ผ์ ๋๋ ธ์๋๋ฐ ์์ง ๋ต์ ์ป์ง ๋ชปํ๋ค.
์ถ๊ฐ: ์ธ ๋๋ ๋ชฐ๋๋๋ฐ ์ด๋ฏธ ์ ํธ์ด ๋ฒ์ญ๋์ด ์์์ต๋๋ค! https://github.com/ES678/Exploring-ES6
ES6 ๋ ๋ณ์๋ฅผ ์ ์ธํ๋ ๋๊ฐ์ง ์๋ก์ด ๋ฌธ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ์๋กญ๊ฒ ๋์
๋ let
๊ณผ const
๋ ES5 ์์ ๋ณ์๋ฅผ ์ ์ธํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ var
์ ๊ฑฐ์ ์๋ฒฝํ ๋์ฒดํ ์ ์์ต๋๋ค.
let
let
์ var
๊ณผ ์ ์ฌํ๊ฒ ๋์ํ์ง๋ง, let
์ด ์ ์ธํ๋ ๋ณ์๋ block-scoped๋ก ํ์ฌ ๋ธ๋ญ์์๋ง ์กด์ฌํฉ๋๋ค. var
์ function-scoped์์ต๋๋ค.
๋ค์ ์ฝ๋์์ let
์ผ๋ก ์ ์ธ๋ ๋ณ์์ธ tmp
๋ line A ์์ ์์ํ๋ ๋ธ๋ญ์์๋ง ์กด์ฌํ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
function order(x, y) {
if (x > y) {
// (A)
let tmp = x
x = y
y = tmp
}
console.log(tmp === x) // ReferenceError: tmp is not defined
return [x, y]
}
const
const
๋ let
๊ณผ ์ ์ฌํ๊ฒ ๋์ํ์ง๋ง, ๋ณ์๋ฅผ ์ ์ธ ์ฆ์ ๋ฐ๋ก ์ด๊ธฐํํด์ค์ผ ํ๊ณ ์ดํ๋ก ๊ทธ ๋ด์ฉ(value)์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
const foo;
// SyntaxError: missing = in const declaration
const bar = 123;
bar = 456;
// TypeError: `bar` is read-only
for-of
๋ loop ๊ฐ ๋ ๋๋ง๋ค ๋ณ์๋ฅผ ์ ์ธํ๋ฏ๋ก, const ๋ก loop ๋ณ์๋ฅผ ์ ์ธํ๋ ๊ฒ๋ ๊ฐ๋ฅํฉ๋๋ค.
for (const x of ['a', 'b']) {
console.log(x)
}
// Output:
// a
// b
์๋ ํ๋ ES6 ์์ ๋ณ์๋ฅผ ์ ์ธํ๋ 6 ๊ฐ์ง ๋ฐฉ๋ฒ์ ๋ํด ์ ๋ฆฌํด ๋์ ๊ฒ์ ๋๋ค.
![6 ways of declaring variables]({{ site.baseurl }}/images/var-cheatsheet.png)
let
๊ณผ const
๋ฅผ ํตํ block scopinglet
๊ณผ const
๋ ๋ค block-scoped๋(๋ณ์๋ฅผ ๊ฐ์ธ๋ ๊ฐ์ฅ ์์ชฝ์ ๋ธ๋ญ์์๋ง ์กด์ฌํ๋) ๋ณ์๋ฅผ ์ ์ธํฉ๋๋ค. ์๋์ ์ฝ๋์ const
๋ก ์ ์ธ๋ tmp
๋ณ์๋ if ๋ฌธ์ then-block ์์๋ง ์กด์ฌํฉ๋๋ค.
function func() {
if (true) {
const tmp = 123
}
console.log(tmp) // ReferenceError: tmp is not defined
}
๋ฐ๋ฉด var
๋ก ์ ์ธ๋ ๋ณ์๋ function-scoped ๋์ด์์ต๋๋ค.
function func() {
if (true) {
var tmp = 123
}
console.log(tmp) // 123
}
Block scoping ์์๋ ํจ์ ๋ด์์ ์ ์ ๋ณ์๋ฅผ ๋ฎ๋ ๊ฒ(์๋ฌธ: shadow)๋ ๊ฐ๋ฅํฉ๋๋ค.
function func() {
const foo = 5;
if (ยทยทยท) {
const foo = 10; // shadows outer `foo`
console.log(foo); // 10
}
console.log(foo); // 5
}
const
๋ ๋ถ๋ณํ๋(immutable) ๋ณ์๋ฅผ ๋ง๋ญ๋๋คlet
์ผ๋ก ์ ์ธํ ๋ณ์๋ ๋ณ๊ฒฝ๊ฐ๋ฅ(mutable)ํฉ๋๋ค.
let foo = 'abc'
foo = 'def'
console.log(foo) // def
const
๋ก ์ ์ธ๋ ์์๋ ๋ถ๋ณ, ๋ค๋ฅธ ๊ฐ์ ํ ๋นํ ์ ์์ต๋๋ค.
(strict ๋ชจ๋์ ์๊ด์์ด TypeError
๋ฅผ ๋ด๋์ต๋๋ค)
const foo = 'abc'
foo = 'def' // TypeError
const
๋ ๋ณ์์ ๊ฐ์ ๋ถ๋ณํ๊ฒ ๋ง๋ค์ด์ฃผ์ง๋ ์์ต๋๋คconst
๋ ๋ณ์๊ฐ ํญ์ ๊ฐ์ ๊ฐ์ ๊ฐ์ง๊ณ ์๋ค๋ ๋ป์ผ ๋ฟ, ๊ทธ ๊ฐ ์์ฒด๊ฐ ๋ณํ ์ ์๋ค๋ ๋ป์ ์๋๋๋ค. ์๋์ ์์์ obj
๋ ๋ถ๋ณ์ด์ง๋ง ๊ทธ๊ฒ์ด ๊ฐ๋ฆฌํค๊ณ ์๋ ๊ฐ์ ๋ณํ ์ ์์ด์ ์ฐ๋ฆฌ๊ฐ ์์ฑ์ ๋ํ ์ ์์ต๋๋ค.
const obj = {}
obj.prop = 123
console.log(obj.prop) // 123
๋ฌผ๋ก obj
์ ๋ค๋ฅธ ๊ฐ์ ํ ๋นํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
obj = {}; // TypeError
๋ง์ฝ obj
์ ๊ฐ ์์ฒด๋ฅผ ๋ถ๋ณํ๊ฒ ํ๊ณ ์ถ์ ๋๋ freeze ๋ฑ์ ์ด์ฉํ ์ ์์ต๋๋ค.
const obj = Object.freeze({})
obj.prop = 123 // TypeError
Object.freeze()
๋ shallow
ํฉ๋๋ค.Object.freeze()
๊ฐ shallow, ์ฆ ๋์์ property
๋ง์ freeze
ํ ๋ฟ object
๋ก ๋์ด์๋ property
๊น์ง freeze
ํ์ง๋ ์์ต๋๋ค. ์๋ ์ฝ๋์์ obj
๋ freeze
๋์์ง๋ง,
> const obj = Object.freeze({ foo: {} });
> obj.bar = 123
TypeError: Can't add property bar, object is not extensible
> obj.foo = {}
TypeError: Cannot assign to read only property 'foo' of #<Object>
obj.foo
๋ ๊ทธ๋ ์ง ์์ต๋๋ค.
> obj.foo.qux = 'abc';
> obj.foo.qux
'abc'
const
const
๋ณ์๊ฐ ํ ๋ฒ ์ ์ธ๋๊ณ ๋๋ฉด ๊ทธ ๊ฐ(๋ฌด์์ ๊ฐ๋ฆฌํค๊ณ ์๋์ง)๋ ๋ณํ ์ ์์ต๋๋ค. ํ์ง๋ง ๊ทธ๋ ๋ค๊ณ ํด์ scope ์ ๋ค์ ๋ค์ด๊ฐ ๋ณ์๋ฅผ ์๋กญ๊ฒ ์ ์ธํ ์ ์๋ ๊ฒ์ ์๋๋๋ค. ์๋ ์ฝ๋๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
function logArgs(...args) {
for (const [index, elem] of args.entries()) {
const message = index + '. ' + elem
console.log(message)
}
}
logArgs('Hello', 'everyone')
// Output:
// 0. Hello
// 1. everyone
let
๊ณผ const
๋ก ์ ์ธ๋ ๋ณ์๋ temporal dead zone
(TDZ)๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ๋ณ์์ scope ์ ๋ค์ด๊ฐ๋๋ผ๋ ์ ์ธ๋ถ๋ถ์ด ์คํ๋๊ธฐ ์ ์๋ ์ ๊ทผ(get
๋๋ set
)์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค. TDZ ๊ฐ ์๋ var
๋ก ์ ์ธ๋ ๋ณ์(์ดํ var
๋ณ์)์ TDZ ๋ฅผ ์ง๋ let
์ผ๋ก ์ ์ธ๋ ๋ณ์(let
๋ณ์)์ ์์ ์ฃผ๊ธฐ๋ฅผ ๋น๊ตํด๋ด
์๋ค.
var
๋ก ์ ์ธ๋ ๋ณ์์ ์์ ์ฃผ๊ธฐvar
๋ณ์์๋ TDZ ๊ฐ ์์ต๋๋ค. var
๋ณ์์ ์์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
var
๋ณ์์ scope(๋๋ฌ์ธ๊ณ ์๋ ํจ์)์ ์ง์
ํ๋ฉด, ๋ณ์๋ฅผ ์ํ ์ ์ฅ์(binding)๊ฐ ์์ฑ๋๋ฉฐ ๋ณ์๋ undefined ๋ก ์ฆ์ ์ด๊ธฐํ๋ฉ๋๋ค.var
๋ณ์๋ initializer
์ ๊ฐ์ ๊ฐ์ง๊ฒ ๋ฉ๋๋ค. ๋ง์ฝ ๊ฐ์ด ์ฃผ์ด์ง์ง ์์๋ค๋ฉด ๋ณ์๋ ๊ณ์ํด์ undefined
๊ฐ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.let
์ผ๋ก ์ ์ธ๋ ๋ณ์์ ์์ ์ฃผ๊ธฐlet
๋ณ์๋ TDZ ๋ฅผ ์ง๋๊ณ ์์ต๋๋ค. let
๋ณ์์ ์์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
let
๋ณ์์ scope(๋๋ฌ์ธ๊ณ ์๋ ๋ธ๋ญ)์ ์ง์
ํ๋ฉด, ๋ณ์๋ฅผ ์ํ ์ ์ฅ์(binding)๊ฐ ์์ฑ๋์ง๋ง ์ด๊ธฐํ๋ ๋์ง ์์ต๋๋ค.ReferenceError
๊ฐ ๋ฐ์ํฉ๋๋ค.let
๋ณ์๋ initializer
์ ๊ฐ์ ๊ฐ์ง๊ฒ ๋ฉ๋๋ค. ๋ง์ฝ ๊ฐ์ด ์ฃผ์ด์ง์ง ์์๋ค๋ฉด ๋ณ์๋ ์ด์ ๋ถํฐ undefined
๊ฐ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.const
๋ณ์๋ let ๋ณ์์ ์ ์ฌํ๊ฒ ๋์ํ์ง๋ง initializer ๋ฅผ ๊ผญ ๊ฐ์ง๊ณ ์์ด์ผํฉ๋๋ค.
TDZ ์์์ ๋ณ์์ ์ ๊ทผํ๋ คํ๋ฉด ์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค.
let tmp = true
if (true) {
// enter new scope, TDZ starts
// Uninitialized binding for `tmp` is created
console.log(tmp) // ReferenceError
let tmp // TDZ ends, `tmp` is initialized with `undefined`
console.log(tmp) // undefined
tmp = 123
console.log(tmp) // 123
}
console.log(tmp) // true
Initializer ๊ฐ ์์ ๊ฒฝ์ฐ TDZ ๋ assignment ๊ฐ ์ด๋ฃจ์ด์ง ํ์ ๋๋ฉ๋๋ค.
let foo = console.log(foo) // ReferenceError
์๋์ ์ฝ๋๋ TDZ ๊ฐ spatial(๊ณต๊ฐ ๊ธฐ๋ฐ)ํ์ง ์๊ณ temporal(์๊ฐ ๊ธฐ๋ฐ)ํจ์ ๋ณด์ฌ์ค๋๋ค.
if (true) {
// enter new scope, TDZ starts
const func = function() {
console.log(myVar) // OK!
}
// Here we are within the TDZ and
// accessing `myVar` would cause a `ReferenceError`
let myVar = 3 // TDZ ends
func() // called outside TDZ
}
typeof
๋ TDZ ์์ ์๋ ๋ณ์์ ๋ํด ReferenceError
๋ฅผ ๋ฐ์ํฉ๋๋ค.๋ง์ฝ TDZ ์์ ์๋ ๋ณ์๋ฅผ typeof ๋ฅผ ํตํด ์ ๊ทผํ๊ณ ์ํ๋ฉด ์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค.
if (true) {
console.log(typeof foo) // ReferenceError (TDZ)
console.log(typeof aVariableThatDoesntExist) // 'undefined'
let foo
}
์ด์ ๋ฅผ ์๊ฐํด๋ด
์๋ค. foo
๋ ์์ง ์ ์ธ๋์ง ์์๊ณ , ๋ฐ๋ผ์ foo ๋ ์ด๊ธฐํ๋์ง๋ ์์์ต๋๋ค(let
๋ณ์๋๊น). ํ๋ก๊ทธ๋๋จธ๋ foo
์ ์กด์ฌ์ ๋ํด ํผ๋์ ํ๊ณ ์์ต๋๋ค. ๋ฐ๋ผ์ ๊ฒฝ๊ณ ๋ฅผ ์ฃผ๋ ๊ฒ์ด ๋ฐ๋์งํด๋ณด์
๋๋ค.
๋ํ ์ด๋ฐ ๋ฅ์ ๊ฒ์ฌ๋ ์กฐ๊ฑด๋ถ๋ก ์ ์ญ ๋ณ์๋ฅผ ์ ์ธํ๋ ๊ฒฝ์ฐ์๋ ์ ์ฉํฉ๋๋ค. ์ด๋ ์ค๋ก์ง ์๋ จ๋ ์๋ฐ์คํฌ๋ฆฝํธ ํ๋ก๊ทธ๋๋จธ๋ค๋ง์ด ํด์ผํ๋ ์ผ์ด๋ฉฐ var
๋ฅผ ํตํด ํ ์ ์์ต๋๋ค. typeof
๋ฅผ ์ด์ฉํ์ง ์๊ณ ๋ ์ ์ญ ๋ณ์๊ฐ ์กด์ฌํ๋์ง๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
// With `typeof`
if (typeof someGlobal === 'undefined') {
var someGlobal = { ยทยทยท };
}
// Without `typeof`
if (!('someGlobal' in window)) {
window.someGlobal = { ยทยทยท };
}
๊ฐ์ฒซ๋ฒ์งธ ๋ฐฉ๋ฒ์ global scope ์์๋ง ์ ํจํ๋ฉฐ ES6 ๋ชจ๋ ์์์๋ ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
(์ญ์ ์ฃผ: ๊ผญ es6 ์๋์ด๋ function(){ {์ฝ๋๋ณต๋ถ} }
ํ๋ ๋๊ตฌ๋ค์์๋ ๋ค ์๋ ๋ฏ..)
const
๋ฅผ ์ํด: const
๋ฅผ ์ณ๊ฒ ๋์ํ๋๋ก ๋ง๋ค๊ธฐ๋ ์ด๋ ต์ต๋๋ค. Allen Wirfs-Brock ๋ฅผ ์ธ์ฉํ๊ฒ ์ต๋๋ค. const
์ ํฉ๋ฆฌ์ ์๋ฏธ(rational semantics)๋ฅผ ๋ถ์ฌํฉ๋๋ค. ์ด ์ฃผ์ ์ ๋ํ ์๋นํ ๊ธฐ์ ์ ๋
ผ์๊ฐ ์์๊ณ ๊ทธ ๊ฒฐ๊ณผ TDZ ๊ฐ ์ ์ผ ์ข์ ๋ฐฉ๋ฒ์ผ๋ก ์๊ฒจ๋ฌ์ต๋๋ค. let
์ญ์ TDZ ๋ฅผ ๊ฐ์ง๊ณ ์์ด let
๊ณผ const
๋ฅผ ๋ฐ๊พธ์ด ์จ๋ ์์์น ๋ชปํ๊ฒ ๋์์ด ๋ณํ๋ ์ผ์ด ์์ต๋๋ค.โundefined
๊ฐ์ ๊ฐ์ง๊ณ ์์ผ๋ฉด ๊ฐ๋๊ฐ ๋ณด์ฅํด์ฃผ๋ ๋ด์ฉ๊ณผ ์ถฉ๋์ด ์ผ์ด๋ ์ ์์ต๋๋ค.
(์ญ์ ์ฃผ: ์ ์ฒ๋ผ guard ์ ๋ํด ์์ํ์ ๋ถ๋ค์ Swift ์ชฝ์์ ์ฐพ์๋ณด์๋ฉด ์ฐธ๊ณ ํ ๋งํ ๊ธ์ด๋ค ๋ง์ต๋๋ค. ์ )let
๊ณผ const
๋ค(์ญ์ ์ฃผ: loop head ๋ for (์ด๊ธฐ๋ฌธ; ์กฐ๊ฑด๋ฌธ; ์ฆ๊ฐ๋ฌธ) <-๊น์ง๋ฅผ ๋งํฉ๋๋ค. โloop ์โ๋ก ๋ฒ์ญํ ๊ธ๋ ์์์ต๋๋ค)
๋ค์ loop ๋ฌธ์ ๋จธ๋ฆฌ์์๋ ๋ณ์ ์ ์ธ์ด ๊ฐ๋ฅํฉ๋๋ค.
for
for-in
for-of
๋ณ์ ์ ์ธ์ ์ํด์๋ var
, let
, const
์ค ํ๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ฐ๊ฐ์ด ์ด๋ป๊ฒ ๋ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๋ด๋๋์ง ์ค๋ช
ํด๋๋ฆฌ๊ฒ ์ต๋๋ค.
for
looploop ๋จธ๋ฆฌ์์ var
๋ฅผ ํตํด ๋ณ์๋ฅผ ์ ์ธํ๋ฉด binding(์ ์ฅ ๊ณต๊ฐ) ํ๋๊ฐ ์๊น๋๋ค.
const arr = []
for (var i = 0; i < 3; i++) {
arr.push(() => i)
}
arr.map(x => x()) // [3,3,3]
3 ๊ฐ์ arrow function ์์ ์๋ 3 ๊ฐ์ i
๋ ๋ชจ๋ ๋์ผํ binding ์ ๊ฐ๋ฆฌํค๊ณ ์๊ณ , ๋ฐ๋ผ์ ๋ชจ๋ ๊ฐ์ ๊ฐ์ ์ถ๋ ฅํฉ๋๋ค.
๋ง์ฝ let
์ ์ด์ฉํด์ ๋ณ์๋ฅผ ์ ์ธํ๋ค๋ฉด loop ๊ฐ ๋ ๋ ๋ง๋ค ์๋ก์ด binding ์ด ์๊น๋๋ค.
const arr = []
for (let i = 0; i < 3; i++) {
arr.push(() => i)
}
arr.map(x => x()) // [0,1,2]
์ด๋ฒ์๋ ๊ฐ๊ฐ์ i
๊ฐ ๊ฐ๊ฐ์ iteration ์ binding ์ ๊ฐ๋ฆฌํค๊ณ ์๊ณ ๊ทธ ๋น์์ ๊ฐ์ ์ง๋๊ณ ์์ต๋๋ค. ๋ฐ๋ผ์ 3 ๊ฐ์ ํจ์๋ ๋ค๋ฅธ ๊ฐ๋ค์ ์ถ๋ ฅํฉ๋๋ค.
const
๋ var
์ฒ๋ผ ๋์ํ์ง๋ง const
๋ก ์ ์ธ๋ ๋ณ์์ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
// TypeError: Assignment to constant variable
// (due to i++)
for (const i = 0; i < 3; i++) {
console.log(i)
}
iteration ๋ง๋ค ์๋ก์ด binding ์ด ์๊ธฐ๋ ๊ฒ์ด ์ด์ํด๋ณด์ผ ์ ์์ง๋ง loop ๋ณ์๋ฅผ ์ฐธ์กฐํ๋ ํจ์๋ค์ ๋ง๋ค๊ธฐ ์ํด loop ๋ฅผ ์ฐ๋ ๊ฒฝ์ฐ์๋ ์์ฃผ ์ ์ฉํฉ๋๋ค. ๋ค์ ์น์ ์์ ๋ ์์ธํ ์ค๋ช ๋๋ฆฌ๊ฒ ์ต๋๋ค.
for-of
loop ๊ณผ for-in
loopfor-of
loop ๋ด์์ var
๋ binding ํ๋๋ฅผ ๋ง๋ญ๋๋ค
const arr = []
for (var i of [0, 1, 2]) {
arr.push(() => i)
}
arr.map(x => x()) // [2,2,2]
let
์ iteration ํ ๋ฒ ๋ง๋ค binding ํ๋๋ฅผ ๋ง๋ญ๋๋ค
const arr = []
for (let i of [0, 1, 2]) {
arr.push(() => i)
}
arr.map(x => x()) // [0,1,2]
const
๋ var
์ฒ๋ผ ๋์ํ์ง๋ง const
๋ก ์ ์ธ๋ ๋ณ์์ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
for-in
loop ๋ด๋ถ์์์ ๋์์ for-of
์ ์ ์ฌํฉ๋๋ค.
(์ญ์์ฃผ: ์คํ์ ๊ดํ ๋ถ๋ถ์ ์๋ตํ์ต๋๋ค. http://exploringjs.com/es6/ch_variables.html#_for-loop-per-iteration-bindings-in-the-spec)
๋ค์์ ๋งํฌ 3 ๊ฐ๋ฅผ ๋ณด์ฌ์ฃผ๋ HTML ํ์ด์ง์ ๋๋ค.
<!doctype html>๊ฐ
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="content"></div>
<script>
const entries = [
['yes', 'ja'],
['no', 'nein'],
['perhaps', 'vielleicht'],
];
const content = document.getElementById('content');
for (let [source, target] of entries) { // (A)
content.insertAdjacentHTML('beforeend',
`<div><a id="${source}" href="">${source}</a></div>`);
document.getElementById(source).addEventListener(
'click', (event) => {
event.preventDefault();
alert(target); // (B)
});
}
</script>
</body>
</html>
line B ์ ์๋ target
๋ณ์์ ์ํด์ ๋ณด์ฌ์ง ๊ฒฐ๊ณผ๋ฌผ์ด ์ ํด์ง๋๋ค. ๋ง์ฝ line A ์์ let
๋์ var
๊ฐ ์ฐ์๋ค๋ฉด, ๋ฃจํ ์ ์ฒด์ ๋ํด์ binding ํ๋๊ฐ ์๊ธฐ๊ณ ๊ทธ ๊ฐ์ ๊ฒฐ๊ตญ ๋ง์ง๋ง์ผ๋ก ์ ์ฅ๋ โvielleichtโ๊ฐ ๋ ๊ฒ์
๋๋ค. ๋ฐ๋ผ์ ์ฐ๋ฆฌ๊ฐ ์ด๋ ๋งํฌ๋ฅผ ๋๋ฅด๋ โvielleichtโ์ด ์ถ๋ ฅ๋ ๊ฒ์
๋๋ค.
ํ์ง๋ง ๊ณ ๋ง๊ฒ๋ let
์ ํตํด์ iteration ๋ง๋ค binding ์ด ์๊ธฐ๊ณ , ๋ฒ์ญ ๊ฒฐ๊ณผ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ถ๋ ฅ๋ฉ๋๋ค.
๋ง์ฝ ํจ๋ฌ๋ฏธํฐ์ ๊ฐ์ ์ด๋ฆ์ ๊ฐ์ง ๋ณ์๋ฅผ let
์ผ๋ก ์ ์ธํ๋ฉด static(load-time)์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค
function func(arg) {
let arg // static error: duplicate declaration of `arg`
}
๊ฐ์ ์ผ์ ๋ธ๋ญ ์์์ํ๋ฉด ํจ๋ฌ๋ฏธํฐ๋ฅผ ์ ์ ๊ฐ๋ฆฝ๋๋ค(shadow)
function func(arg) {
{
let arg // shadows parameter `arg`
}
}
๋ฐ๋ฉด ํจ๋ฌ๋ฏธํฐ์ ๊ฐ์ ์ด๋ฆ์ ๊ฐ์ง ๋ณ์๋ฅผ var
์ผ๋ก ์ ์ธํ ๊ฒฝ์ฐ, ์๋ฌด ์ผ๋ ์ผ์ด๋์ง ์์ต๋๋ค. ์ด๋ ๊ฐ์ scope ์์ var
๋ณ์๋ฅผ ์๋ก ์ ์ธํ๋ฉด ์๋ฌด ์ผ๋ ์ผ์ด๋์ง ์๋ ๊ฒ๊ณผ ๊ฐ์ ์๋ฆฌ์
๋๋ค.
function func(arg) {
var arg // does nothing
}
function func(arg) {
{
// We are still in same `var` scope as `arg`
var arg // does nothing
}
}
๋ง์ฝ ํจ๋ฌ๋ฏธํฐ๊ฐ ๊ธฐ๋ณธ ๊ฐ๋ค์ ๊ฐ์ง๊ณ ์์ผ๋ฉด ์ด๋ค์ let ์ ์ธ์ ์ฐ์์ฒ๋ผ ์ฒ๋ฆฌ๋๊ณ TDZ ๋ฅผ ์ง๋๋๋ค.
// OK: `y` accesses `x` after it has been declared
function foo(x = 1, y = x) {
return [x, y]
}
foo() // [1,1]
// Exception: `x` tries to access `y` within TDZ
function bar(x = y, y = 2) {
return [x, y]
}
bar() // ReferenceError
ํจ๋ฌ๋ฏธํฐ ๊ธฐ๋ณธ๊ฐ์ scope ๋ ํจ์ body ์ ๋ณ๋์ scope ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค(๊ธฐ๋ณธ๊ฐ์ scope ๊ฐ body ๋ฅผ ๊ฐ์๋๋ค). ๋ฐ๋ผ์ ํจ์ ํจ๋ฌ๋ฏธํฐ ๊ธฐ๋ณธ๊ฐ ๋ด์ method ๋ ํจ์๋ body ์ ์ง์ญ ๋ณ์๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
const foo = 'outer'
function bar(func = x => foo) {
const foo = 'inner'
console.log(func()) // outer
}
bar()
์๋ฐ์คํฌ๋ฆฝํธ์ ์ ์ญ๊ฐ์ฒด (๋ธ๋ผ์ฐ์ ์์์ window
, Node.js ์์๋ global
) ๋ ๊ธฐ๋ฅ์ด๋ผ๊ธฐ ๋ณด๋ค๋ ๋ฒ๊ทธ์ ๊ฐ๊น์ต๋๋ค(!), ํนํ ์ฑ๋ฅ ์ธก๋ฉด์์๋ ๋์ฑ ๊ทธ๋ ์ต๋๋ค. ๋๋ฌธ์ ES6 ์์๋ ๋ค์๊ณผ ๊ฐ์ ๊ตฌ๋ถ์ด ๋์
๋์์ต๋๋ค.
var
๋ฅผ ์ด์ฉํ ์ ์ธlet
์ ์ด์ฉํ ์ ์ธconst
๋ฅผ ์ด์ฉํ ์ ์ธ(์ญ์ ์ฃผ: ์ดํด๊ฐ ์ ์๋์ ๋ค์๊ณผ ๊ฐ์ ๋๋์ผ๊น?ํ๊ณ ์ฝ๋๋ฅผ ์ง๋ดค๋๋ฐ babel ์์ let ์ด var ๋ก ๋ฐ๋ก ๋ฐ๋๋ ๋ฐ๋์ ์คํ์ ๋ชปํ์ต๋๋ค)
var a = 1
let b = 1
console.log(window.a)
console.log(window.b)
ํจ์ ์ ์ธ์โฆ
global
๊ฐ์ฒด์ property ๋ฅผ ๋ง๋ญ๋๋ค. ๋ง์น var ์ฒ๋ผ๋ค์ ์ฝ๋๋ ํจ์ ์ ์ธ์ด hoist๋จ์ ๋ณด์ฌ์ค๋๋ค.
{
// Enter a new scope
console.log(foo()) // OK, due to hoisting
function foo() {
return 'hello'
}
}
ํด๋์ค ์ ์ธ์โฆ
global
๊ฐ์ฒด์ property ๋ฅผ ๋ง๋ค์ง ์์ต๋๋ค.ํด๋์ค ์ ์ธ์ด hoist๋์ง ์๋๋ค๋ ์ฌ์ค์ด ๋๋ผ์ธ ์ ์์ต๋๋ค. ์๋ํ๋ฉด ๊ฒฐ๊ตญ ํด๋์ค ์ ์ธ ์ญ์ ํจ์๋ฅผ ๋ง๋ค๊ธฐ ๋๋ฌธ์
๋๋ค. ํ์ง๋ง extends
๋ถ๋ถ์์ ๋ค๋ฅธ ๋ณ์๋ ํจ์๋ฅผ ์ฐธ์กฐํด์ผํ๊ธฐ ๋๋ฌธ์ ํด๋์ค ์ ์ธ์ ์ ์ ํ ์์ ์ ์คํ๋์ด์ผ ํฉ๋๋ค.
{
// Enter a new scope
const identity = x => x
// Here we are in the temporal dead zone of `MyClass`
const inst = new MyClass() // ReferenceError
// Note the expression in the `extends` clause
class MyClass extends identity(Object) {}
}
const
vs. let
vs. var
ํญ์ let
๊ณผ const
์ค ํ๋๋ฅผ ์ด์ฉํ๋๋ก ํ์ธ์.
1) ์ผ๋จ const
๋ฅผ ๊ณ ๋ คํ์ธ์. ๊ฐ์ด ์ ๋ ๋ณํ์ง ์์ ๊ฒฝ์ฐ - ํด๋น ๋ณ์๊ฐ ์ ๋ assignment ์ ์ผ์ชฝ์ ์๊ฑฐ๋ ++, โ ๋์ง ์์ ๊ฒฝ์ฐ - ์ const
๋ฅผ ์ด์ฉํ ์ ์์ต๋๋ค. const
๋ณ์๊ฐ ๊ฐ๋ฆฌํค๊ณ ์๋ ๊ฐ์ฒด์ ์์ ์ ํ์ฉ๋์ด ์์ต๋๋ค.
const foo = {}
foo.prop = 123 // OK
์ฌ์ง์ด const
๋ฅผ for-of
์์ ์ฌ์ฉํ ์๋ ์์ต๋๋ค. Iteration ๋ง๋ค (๋ถ๋ณํ๋)binding ์ด ์๊ธฐ๊ธฐ ๋๋ฌธ์ด์ง์.
for (const x of ['a', 'b']) {
console.log(x)
}
// Output:
// a
// b
for ๋ฌธ ์์์ x ๋ ์์ ๋ ์ ์์ต๋๋ค.
2) ์๋๋ผ๋ฉด, let
์ ์ฌ์ฉํ์ธ์ - ๋ณ์์ ์ด๊ธฐ๊ฐ์ด ๋์ค์ ๋ฐ๋ ๊ฒฝ์ฐ์
let counter = 0 // initial value
counter++ // change
let obj = {} // initial value
obj = { foo: 123 } // change
3) var
๋ ์ฐ์ง ๋ง์ธ์
๋ง์ฝ ์์ ์์น์ ๋ฐ๋ฅธ๋ค๋ฉด var
๋ ๋ ๊ฑฐ์ ์ฝ๋์์๋ง ๋ํ๋ ๋ฆฌํฉํ ๋ง์ ์ ์คํจ์ด ์๊ตฌ๋จ์ ์๋ฆด ๊ฒ์
๋๋ค.
let
์ด๋ const
๋ ํ ์ ์๊ณ , var
๋ ํ ์ ์๋ ์ผ์ด ์์ต๋๋ค: (global scope ์์) var
๋ก ์ ์ธ๋ ๋ณ์๋ global
๊ฐ์ฒด์ property ๊ฐ ๋ฉ๋๋ค. ํ์ง๋ง ๋ณดํต ์ด๋ ์ข์ ์ผ์ด ์๋๋๋ค. ํ์ํ ๊ฒฝ์ฐ window
๋ global
์ property ๋ฅผ assign ํด์๋ ๊ฐ์ ์ผ์ ํ ์ ์์ต๋๋ค.
์์ ๊ท์น์ ๋์์ผ๋ก const
๋ฅผ completely immutable ํ ๊ฒฝ์ฐ์๋ง(primitive value ๋ frozen object) ์ด์ฉํ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ์ด์ ์ฐ๋ฆฌ๋ ๋๊ฐ์ง ์ต์
์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
const
(์ถ์ฒ): const
๋ immutable ํ binding์ ๋ปํฉ๋๋คlet
(๋์): const
๋ immutable ํ value๋ฅผ ๋ปํฉ๋๋ค๋ ๊ฐ์ ์ฐ์ด์ ๊ฐ๋ฆฌ๊ธฐ๋ ํ๋ญ๋๋ค. ๋ค๋ง ์ ๋ 1 ๋ฒ์ ์์ฃผ ์ฝ๊ฐ ์ ํธํฉ๋๋ค.
๋ฒ์ญ ํ๊ธฐ