책)러닝 자바스크립트 - weakMap 사용, for of 사용
러닝자바스크립트 p.243~
const naughty = new WeakSet();
const children = [
{name: 'suzi'},
{name: 'bibi'}
]
naughty.add(children[1]);
for (let child of children){
if(naughty.has(child)) console.log(`Coal for ${child.name}`);
else console.log(`prensent for ${child.name}`);
}
//VM41:11 prensent for suzi
//VM41:10 Coal for bibi
//undefined
<객체의 단점>
1. 프로토 체인 때문에 의도하지 않은 연결이 생길 수 잇다.
2. 객체 안에 연결된 키와 값이 몇개인지 쉽게 알아낼 수 없다.
3. 키는 반드시 문자열이나 심볼이어야하므로 객체를 키로 써서 값과 연결할 수 없다.
4. 객체는 프로퍼티 순서를 보장하지 않는다.
< 맵 >
1. 맵 객체 만들기
const userRoles = new Map();
2. 맵의 set() 메서드를 써서 사용자 역할을 할당한다.
userRoles.set(u1, 'user');
= userRoles.set(u1, 'user').set(u2, 'user').set(u3, 'admin);
>>체인으로 연결 가능
생정자에 배열의 배열을 넘기는 형태로 써도 됩니다.
const userRoles = new Map([
[u1, 'user'], [u2, 'user'], [u3, 'admin']
]);
3. u2 의 역할을 알아볼 때는 get 메서드를 쓴다.
userRoles.get(u2);
//'user'
맵에 존재하지 않는 키에 get을 호출하면 undeifned 를 반환한다.
맵에 키가 존재하는지 확인하는 has() 메서드도 있다.
4. 맵에 이미 존재하는 키에 set() 을 호출하면 값이 교체됩니다.
userRoles.set(u2, 'admin);
userRoles.get(u2) // admin;
5. userRoles.size //3
맵의 요소 숫자를 반환합니다.
6. keys() , values, entires() + for of
// 이터러블 객체를 반환한다.
배열이 필요하면 확산 연산자를 쓴다.
[...userRoles.values()]; // ['user','user','admin']
<위크맵>
<셋>
중복을 허용하지 않는 데이터 집합.
같은 사용자에게 같은 연할을 여러번 부여한다는 건 상직적이지 않죠 이럴때씁니다,
const roles = new Set();
rules.add("user");
roles.add("admin");// Set ["user", "admin" ]
roles.size; // 2
roles.add("user"); /// Set ["user", "admin" ]
<11> 예외와 에러처리
js에는 내장된 Error 객체가 있고 이 객첸 에러 처리에 간편하게 사용할수 있다.
const err = new Error('invalid email');
Error 인스턴스를 만드는 것만으로는 아무일도 일어나지 않는다. 이 인스턴스는 에러와 통신하는 수단이다.
instanceof 연산자를 써서 Error 인스턴스가 반환됐는지 확인한다. 에러 메세지는 message프로퍼티에 있다.
function validateEmail(email){
return email.math(/@/)
? email
: new Error(`invalid email ${email}`);
const email = 'aaa@dom.com';
const validatedEmail = validateEmail(email);
if(validatedEmail instanceof Error) {
console.log(`Error : ${validatedEmail.message}`);
}else {
console.log(`ValidEmail`);
}
예외처리는 try/ catch 문을 사용합니다.
뭔가를 시도하고 예외가 있으면 캐치한다는 뜻이다.
예상하지 못한 에러가 일어날 가능성은 풍부한데
에러가 들어오면 프로그램은 앞뒤 설명없이 멈춰버리겠죠
const email = null;
try{
const validatedEmail = validateEmail(email);
if(validatedEmail instanceof Error) {
console.log(`Error : ${validatedEmail.message}`);
}else {
console.log(`ValidEmail`);
}
} catch(err) {
console.log(`Err: ${err.message}`);
}
에러를 일어켜서 예외 처리 작업을 할 수도 있다 -> throw, raise
catch는 객체뿐만 아니라 어떤 값이든 받을 수 있지만 일반적으로 Error 인스턴스를 넘기는게 편하다.
function billPay(amount, payee, account){
if(amaount > account.balance){
trow new Error("insufficient Funds");
account.transfer(payee, amount);
}
에러를 캐치하면 호출 스택에서 문제 해결에 유용한 정보를 얻을 수 있다. 예를 들면 함수 a가 함수 b를 호출하고 b 가 호출한 c 에서 에러가 났다면 호출 스택은 c에서 일어난 에러를 보고하는데 그치지 않고 b가 c를 호출했으며 b는 a에서 호출했다는 것도 함꼐 알려준다. 대부부분의 자바스크립트 환경에서 Error 인스턴스에는 스택을 문자열로 표현한 stck 프로퍼티가 있다. 이 기능은 표준은 아니지만 대부분의 환경에서 지원합니다.
try...catch...finally
try 블록 코드가 HTTP연결이나 파일같은일종의 자원을 처리할 떄가 잇습니다. 프로그램에서 이 자언을 계속 가지고 있을 수는 없으므로 에러가있든 없는 어느 시점에서는 이 자원을 해제해야 합니다. try 블록에는 문을 원하는 만큼 쓸 수 있고 그 중 어디서든 에러가 일어나서 자원을 해제할 기회가 아예 사라질 수 도 있으므로 try 블록에서 자원을 해제하는 건 안전하지 않습니다. 에러가 일어나지 않으면 실행되지 않는 catch 블록 역시 안전하지 않습니다. 이런 상황에서 finally블록이 필요하다. finally 블록은 에러가 일어나든 않든 반드시 호출된다.
예외처리는 예상할 수 없는 상황에 대비한 마지노선으로 생각하고 예상할 수 있는 에러는 조건문으로 처리하는 것이 최선입니다.
es6
https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Iterators_and_Generators
반복기 및 생성기
컬렉션 내 각 항목 처리는 매우 흔한 연산입니다. JavaScript는 간단한 for 루프에서 map() 및 filter()에 이르기까지, 컬렉션을 반복하는 많은 방법을 제공합니다. 반복기(iterator) 및 생성기(generator)는 반복 개념을 핵심 언어 내로 바로 가져와 for...of 루프의 동작(behavior)을 사용자 정의하는 메커니즘을 제공합니다.
developer.mozilla.org
<이터레이터>
배열에 values() 메서드를 써서 이터레이터를 만들 수 있다. - 현재 호환성 등 확인할 것.
읽기 시작하면 이터레이터의 next() 메서드를 호출한다. 이 메서드가 반환하는 개체에는 value 프로퍼티와 done 프로퍼티(마지막 요소를 읽으면 true로 바뀐다)가 있다.
next()에서 마지막요소를 반환했다해서 끝난건 아니다. value 는 undeifned가 되지만 next는 계속 호출할 수가 있다.
<제너레이터generator>
이터레이터를 사용해 자신의 실행을 제어하는 함수
일반적인 함수는 매개변수를 받고 값을 반환하지만 호출자는 매개변수 외에는 함수의 실행을 제어할 방법이 전혀 없다. 함수를 호출하면 그 함수가 종료될 때까지 제어권을 완전히 넘기는 것이다. 제너레이터는 안그럼
두가지 새로운 개념이 도입되는데,
1. 제너레이터는 언제든 호출자에게 제어권을 넘길수 있다. (yield)
2. 제너레이터는 호출한 즉시 실해오디지는 않는다. 대신 이터레이털를 반환하고 이터레이터의 next 메서드를 호출함에 따라 실행된다.
제너레이터를 만들 때는 function키워드 뒤에 애스터리스크(*)를 붙인다. 이것을 제외하면 문법은 일반적인 함수와 같다. 제너레이터에서는 return 외에 yield 키워드를 쓸 수 있다.
function* rainbow(){
yield 'red';
yield 'orange';
yield 'yellow';
yield 'green';
yield 'blue';
yield 'indigo';
yield 'violet';
}
//제너레이터를 호출하면 이터레이터를 얻는다.
const it = rainbow();
it.next();// {value: "red", done: false}
it.next();// {value: "orange", done: false}
it.next();// {value: "yellow", done: false}
it.next();// {value: "green", done: false}
it.next();// {value: "blue", done: false}
it.next();// {value: "indigo", done: false}
it.next();// {value: "violet", done: false}
it.next();// {value: undefined, done: true}
for(let color of rainbow()){
console.log(color);
}
yeild 는 표현식이고 값으로 평가된다. -> yield 표현식의 값은 호출자가 제너레이터의 이터레이터에서 next를 호출할 때 제공하는 매개변수이다.
제너레이터는 화살표 표기법으로 만들 수 없으며 반드시 function* 을 써야 한다.
yield 문은 마지막 문이더라도 제너레이터를 끝내지 않는다. 제너레이터에서 return 문을 사용하면 그 위치와 관계없이 done은 true가 되고 value프로퍼티는 return이 반환하는 값이 된다.
!! 제너레이터에서 중요한 값을 return으로 반환하지 마요
제너레이터가 반환하는 값을 사용하려 할 때는 yeild를 써야하고, return은 중간에 종료하는 목적으로만 사용해야 한다.
따라서 제너레이터에서 return을 쓸 때는 반환값을 쓰지 않는 습관을 들이도록 한다.
이제 함수를 호출하는 부분에서 데이터를 제공하고 호출한 함수가 완료되길 기다렸다가 반환값을 받는 사고방식에 얽매일 필요 없다.
제너레이터는 모든 연산을 지연시켰다가 필요할 때만 수행하게 만들 수 있다.
이를 통해 비동기적 실행을 개선할 수 있다.