block scope로 변수 선언
block scope | binds to this | hoisted | redeclation | reinitialization | |
---|---|---|---|---|---|
var | X | if global | O | O | O |
let | O | X | X | X | O |
const | O | X | X | X | X |
❗️ let/const는 호이스팅 되지않는 것이 아니라 영향을 받지 않는 것, TDZ에 들어가 실제 있는 위치에 도달할 때까지 액세스 할 수 없음
// var - function scope
var v; // 초기값 필요없음
var v = 321; // 변수 재선언 가능
v = 234; // 재할당 가능
console.log("v : ", v);
// let - Block scope (일반적 언어들)
let l; // 초기값 필요없음
let l = 321; // 재선언 불가 : Identifier 'l' has already been declared
l = 234; // 재할당 가능
console.log("l : ", l);
// const - Block scope
const c; // 초기값 필요 Missing initializer in const declaration //
const c = 321; // 재선언 불가 : Identifier 'c' has already been declared
c = 234; // 재할당 불가
console.log("c : ", c);
//---------------------------------------------------------------------------
function funcScope() {
var v1 = 123;
if (true) {
var v1 = 123;
let ll = 'abc';
}
console.log('let은 Block Scope, ll : ', ll); // 블락 바깥에서 사용 불가 ; ll is not defined
}
funcScope();
console.log('var은 function Scope, v1 : ', v1); // 함수 바깥에서 변수 사용 불가
function 키워드 대신 화살표(=>)를 사용하여 보다 간략한 방법으로 함수를 선언
익명함수 - 콜백함수에서 간결, this는 상위 스코프 this
// 매개변수 지정 방법
() => { ... } // 매개변수가 없을 경우
x => { ... } // 매개변수가 한 개인 경우, 소괄호를 생략할 수 있다.
(x, y) => { ... } // 매개변수가 여러 개인 경우, 소괄호를 생략할 수 없다.
// 함수 몸체 지정 방법
x => { return x * x } // single line block
x => x * x // 함수 몸체가 한줄의 구문이라면 중괄호를 생략할 수 있으며 암묵적으로 return된다. 위 표현과 동일하다.
() => { return { a: 1 }; }
() => ({ a: 1 }) // 위 표현과 동일하다. 객체 반환시 소괄호를 사용한다.
() => { // multi line block.
const x = 10;
return x * x;
};
// ES5
var pow = function (x) { return x * x; };
console.log(pow(10)); // 100
// ES6
const pow = x => x * x;
console.log(pow(10)); // 100
❗️주의 : arrow function 사용하면 안되는 경우
단축 표기법, 선언문에서 프로토타입 설정, 메서드 정의 지원
// ES5
var obj = { name: name, age: age, email: email }; // 기존 표기법
// ES6
let obj = { name, age, email }; // 속성명과 변수명이 같을 경우
let obj = {
func: function(param) { // ES5
...
},
func(param) { // ES6
...
}
}
var a = 5;
var b = 10;
// ES5
console.log("Fifteen is " + (a + b) + " and\nnot " + (2 * a + b) + ".");
// ES6
console.log(`Fifteen is ${a + b} and
not ${2 * a + b}.`);
❗️ + 연산은 불필요한 연산처리를 발생시키므로 템플릿 리터럴을 사용하는 것이 좋음
iterator 기반의 컬렉션 전용 반복문
// for .. of
let cars = ["BMW", "Volvo", "Mini"];
for (const of cars) {
console.log(car + "<br >");
}
이전 버전의 자바스크립트 버전은 함수를 이용해 유사 클래스를 만드는 방법을 사용해왔는데 ES2015에서는 공식적으로 클래스를 지원
다른 프로그래밍 언어의 클래스와 유사하게 생성자(Constructor), 정적 메서드(Static Methhod), 인스턴스 메서드(Instance Method)를 모두 지원
또한 ES2015는 상속도 지원한다.
// 함수형
function TodoList(data, queryId) {
this.todos = data
this.render = function () {
document.querySelector(queryId).innerHTML =
this.todos
.map(todo => todo.isCompleted ? `<li><s>${todo.text}</s></li>` :
`<li>${todo.text}</li>`)
.join('\n')
}
this.setState = function (nextData) {
this.todos = nextData
this.render()
}
}
// 클래스형
class TodoList {
constructor(data, queryId) {
this.todos = data
this.queryId = queryId
}
render() {
document.querySelector(
this.queryId
).innerHTML = this.todos
.map((todo) =>
todo.isCompleted ?
`<li><s>${todo.text}</s></li>` :
`<li>${todo.text}</li>`
)
.join('\n')
}
setState(nextData) {
this.todos = nextData
this.render()
}
}
비동기 처리에 사용되는 객체,
비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냄
Promise는 다음 중 하나의 상태를 가짐
let myPromise = new Promise(function(myResolve, myReject) {
// "Producing Code" (May take some time)
myResolve(); // when successful
myReject(); // when error
});
// "Consuming Code" (Must wait for a fulfilled Promise).
myPromise.then(
function(value) { /* code if successful */ },
function(error) { /* code if some error */ }
);
Symbol()로부터 반환되는 모든 심볼 값은 고유함. 객체 프로퍼티에 대한 식별자로 사용
원시 타입으로 이름 충돌의 위험 없이 프로퍼티의 키로 사용할 수 있음.
let obj = {}
const symbol2 = Symbol(42);
console.log(symbol2 === 42);
// expected output: false
obj[symbol2] = 111;
Set 객체는 자료형에 관계 없이 원시 값과 객체 참조 모두 유일한 값을 저장할 수 있습니다
집합 개념과 유사, 검색 속도 빠름
const set1 = new Set([2, 3, 4, 5]);
mySet.add(1);
console.log(set1.has(1));
// expected output: true
mySet.delete(5); // set에서 5를 제거함
mySet.has(5); // false, 5가 제거되었음
함수 파라미터의 기본 값 지정 가능
function myFunction(x, y = 10) {
// y is 10 if not passed or undefined
return x + y;
}
myFunction(5); // will return 15
이터러블요소 앞에 ...
를 붙여 개별요소로 만들 수 있다.
const array = [1, 2, 3]
console.log(array) // [1, 2, 3]
console.log(...array) // 1 2 3
❗️ 불변성으로 인한 문제 방지용 객체 및 배열 복사
const newData = [...arr]
console.log(newData) // [1, 2, 3]
❕ concat 대신 사용
const arr1 = [1, 2, 3]
const arr2 = ['a', 'b', 'c']
console.log([...arr1, ...arr2])
// [1, 2, 3, 'a', 'b', 'c']
배열, 객체 등을 필요한 부분만 분해하여 추출할 수 있다
❗️ 배열은 순서대로, 객체는 순서가 중요하지 않다.
❕모든 요소 분해
const numbers = [1, 2, 3]
const [first, second, third] = numbers
const obj = {a: 1, b: 2, c: 3}
const {c, b, a} = obj // 3 2 1
❕필요 요소 분해
const chars = ['a', 'b', 'c', 'd', 'e', 'f']
const [a, b, c, ...rest] = chars
console.log(rest) // ['d', 'e', 'f']
const obj = {a: 1, b: 2, c: 3, d: 4}
const {a, b, ...rest} = obj
console.log(rest) // {c: 3, d: 4}
나머지 연산자로 가변배열 값을 설정할 수 있음
function sum(...args) {
let sum = 0;
for (let arg of args) sum += arg;
return sum;
}
let x = sum(4, 9, 16, 25, 29, 100, 66, 77); //326
마지막 parameter에 ...를 붙여서 Arguments를 분리한 후 필요한 부분을 함께 사용할 수 있음
const addPeople = (first, ...developers) => {
const FIRST = first // 'kim'
const DEVELPOERS = developers
// [ 'lee', 'ko', 'um', 'choi']
}
addPeople('kim', 'lee', 'ko', 'um', 'choi')
Number, Array, String, Object와 관련된 많은 속성 추가
Number.EPSILON //두 개의 표현 가능한 숫자 사이의 최소 간격.
Number.MAX_SAFE_INTEGER //JavaScript에서 안전한 최대 정수. (253 - 1)
Number.MAX_VALUE
'hellworld'.includes('hello')
'hellworld'.repaet(3)
[1, 2, 3, 4].find(x => x===3) //첫 번째 요소 반환
[1, 2, 3, 4].findIndex(x => x===3) //첫 번째 요소 인덱스 반환
["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"]
["a", "b", "c"].keys() // iterator 0, 1, 2
["a", "b", "c"].values() // iterator "a", "b", "c"
Object.assign(Point, { origin: new Point(0,0) })
Proxy 객체는 기본적인 동작(속성 접근, 할당, 순회, 열거, 함수 호출 등)의 새로운 행동을 정의할 때 사용, 호스트 객체에 다양한 기능을 추가하여 객체를 생성
var handler = {
get: function(target, name){
return name in target?
target[name] :
37;
}
};
var p = new Proxy({}, handler);
p.a = 1;
p.b = undefined;
console.log(p.a, p.b); // 1, undefined
console.log('c' in p, p.c); // false, 37
모듈
애플리케이션을 구성하는 개별적 요소로서 재사용 가능한 코드 조각
일반적으로 모듈은 파일 단위로 분리되어 있으며 애플리케이션은 필요에 따라 명시적으로 모듈을 로드하여 재사용
ES6부터 module 기능 등장
<script type="module" src="hello.mjs"></script>
기존에 자바스크립트를 불러오는 코드에 type="module" 옵션을 추가해주면 모듈을 불러올 수 있습니다. 쉽게 구분하고 사용할 수 있도록 mjs 확장자를 사용하는 것을 추천
// calculator.js
module.exports = {
add: (a, b) => {
return a + b;
},
subtract: (a, b) => {
return a - b;
},
multiply: (a, b) => {
return a * b;
},
divide: (a, b) => {
return (b != 0) ? (a / b) : "can't divide with 0"
}
}
//main.js
import { add, subtract } from './calculator.js';
console.log('add : ' + add(5, 1));
console.log('subtract : ' + subtract(5, 1));