자바스크립트 복습 - 9

Stulta Amiko·2022년 5월 17일
0

자바스크립트 복습

목록 보기
9/12
post-thumbnail

제너레이터

제너레이터는 원하는 만큼 코드 실행을 시작하거나 중지할 수 있는 함수이다.
중지된 제너레이터 함수를 다시 시작할 떄 데이터를 추가로 전달하면서 재시작 할 수 있다.

function* fruitList() {
    yield 'Banana';
    yield 'Apple';
    yield 'Orange';
}

const fruits = fruitList();

console.log(fruits.next());
console.log(fruits.next());
console.log(fruits.next());
console.log(fruits.next());

실행결과
{ value: 'Banana', done: false }
{ value: 'Apple', done: false }
{ value: 'Orange', done: false }
{ value: undefined, done: true }

위는 간단한 제너레이터 함수를 이용하는 코드이다.
.next()를 이용해서 함수의 실행을 시작한다.
마지막으로 값을 다 보여주고 .next()를 호출하면 undefined 값과
done: true가 반환된다.

const fruitList = ['Banana', "Apple", "Orange", "Melon"];

function* loop(arr) {
    for (const item of arr) {
        yield `I like to eat ${item}s`;
    }
}

const fruitGenerator = loop(fruitList);

console.log(fruitGenerator.next());
console.log(fruitGenerator.next());
console.log(fruitGenerator.next());
console.log(fruitGenerator.next());

실행결과
{ value: 'I like to eat Bananas', done: false }
{ value: 'I like to eat Apples', done: false }
{ value: 'I like to eat Oranges', done: false }
{ value: 'I like to eat Melons', done: false }

다음과 같이 함수를 이용해서 제너레이터에 yield 시킬 수 있다.

만약 값만 가져오고 싶을때는 .next().value를 사용하면 뒤에 done 없이
value만 가져올 수 있다.

.return()

return() 메소드는 제공된 값을 반환하고 Generator를 종료시킨다.

gen.retrun(value) 를 하게되면 value를 리턴하는 메서드이다.

const fruitList = ['Banana', "Apple", "Orange", "Melon"];

function* loop(arr) {
    for (const item of arr) {
        yield `I like to eat ${item}s`;
    }
}

const fruitGenerator = loop(fruitList);

console.log(fruitGenerator.next());
console.log(fruitGenerator.next());
console.log(fruitGenerator.next());
console.log(fruitGenerator.return("WaterMelon"));
console.log(fruitGenerator.next());

실행결과
{ value: 'I like to eat Bananas', done: false }
{ value: 'I like to eat Apples', done: false }
{ value: 'I like to eat Oranges', done: false }
{ value: 'WaterMelon', done: true }
{ value: undefined, done: true }

위 코드에서 보는것처럼 마지막값인 melon을 next()할때 값이 사라지고 중간에 return 하는것으로 대체되었다.

.throw()

throw는 에러를 던진다.

function* gen() {
    try {
        yield "Trying...";
        yield "Trying...2";
        yield "Trying...3";
    } catch (err) {
        console.log("Error: " + err);
    }
}

const myGenerator = gen();
console.log(myGenerator.next());
console.log(myGenerator.next());
console.log(myGenerator.throw("err"));

실행결과
value: 'Trying...', done: false }
{ value: 'Trying...2', done: false }
Error: err
{ value: undefined, done: true }

위와같이 반환할 수 있는 yield가 하나 더 남아있음에도 불구하고 에러를 띄우고 undefined로 넘어가는 모습을 볼 수 있다.

제너레이터와 프로미스 같이 사용하기

const myPromise = () => new Promise((resolve) => {
    resolve("value : ");
});

function* gen() {
    let result = "";
    yield myPromise().then(data => { result = data });
    yield result + ' 2';
};

const asyncFunc = gen();
const val1 = asyncFunc.next();
console.log(val1); // { value: Promise { <pending> }, done: false }

val1.value.then(() => {
    console.log(asyncFunc.next()); //{ value: 'value :  2', done: false }
});

처음 next()를 호출했을때는 프로미스가 아직 완료되지 않았던 상태여서
프로미스의 값이 없는 상태로 출력된다.
마지막 줄에 .then()을 실행하면서 내부에서 next()를 했을때는 프로미스가 완료된 시점이니 값을 정상적으로 출력하는 모습을 볼 수 있다.

프록시

MDN에서는 프록시를 다음과 같이 설명한다.

Proxy 객체는 기본적인 동작(속성 접근, 할당, 순회, 열거, 함수 호출 등)의 새로운 행동을 정의할 때 사용합니다.

new Proxy(target, handler);

프록시를 생성하는 방법은 위와 같다.
target에 들어갈수 있는것은 객체 함수 다른 프록시 무엇이든 가능하다.
handler에는 작업이 수행될 때 프록시의 동작을 정의하는 객체이다.

const dog = { breed: "chihuahua", age: 5 };

const dogProxy = new Proxy(dog, {
    get(target, breed) {
        return target[breed].toUpperCase();
    },
    set(target, breed, value) {
        console.log("changing breed to");
        target[breed] = value;
    }
});

console.log(dogProxy.breed); //CHIHUAHUA

console.log(dogProxy.breed = "Labrador"); //changing breed to Labrador

console.log(dogProxy.breed); //LABRADOR

위 코드에서 프록시를 사용하는 간단한 코드를 볼 수 있다.
dog에서 값을 얻을때 get메서드에서 대문자로 바꿔서 출력하는것과
값을 수정하려고 set메서드를 호출할때도 중간에 짧은 메시지를 띄우고 실행되는 모습을 볼 수 있다.

const validataAge = {
    set: function(object, property, value) {
        if (property === 'age') {
            if (value < 18) {
                throw new Error('too young');
            } else {
                object[property] = value;
                return true;
            }
        }
    }
};

const user = new Proxy({}, validataAge);
user.age = 17;

console.log(user.age = 22); //22

위와같이 프록시를 이용하면 간단하게 예외를 적용하면서 코드를 짤수 있다.
만약 겟터와 셋터를 이용해서 프록시 없이 짜는 경우에는 코드길이가 엄청나게 길어질 것이다.

세트

MDN은 세트를 다음과 같이 설명한다.

Set 객체는 자료형에 관계 없이 원시 값과 객체 참조 모두 유일한 값을 저장할 수 있습니다.

const Plane = new Set();

Plane.add("B737");
Plane.add("B747");
Plane.add("B777");
Plane.add("B747");
console.log(Plane); //Set(3) { 'B737', 'B747', 'B777' }

마지막에 B747을 한번더 추가했으나 출력결과를 보면 B747은 한번더 추가되지 않았다.
이는 세트가 고유한 값을 가지기 때문이다.

const Plane = new Set();

Plane.add("B737");
Plane.add("B747");
Plane.add("B777");
Plane.add("B747");
console.log(Plane.size); //3
console.log(Plane.keys()); //[Set Iterator] { 'B737', 'B747', 'B777' }
console.log(Plane.entries()); //[Set Entries] { [ 'B737', 'B737' ], [ 'B747', 'B747' ],  [ 'B777', 'B777' ]}
console.log(Plane.values()); // [Set Iterator] { 'B737', 'B747', 'B777' }
console.log(Plane.delete("B747")); // true
console.log(Plane); //Set(2) { 'B737', 'B777' }
Plane.clear();
console.log(Plane); //Set(0) {}

set에서 사용할수 있는 메서드들이 어느것이 있는지 간단히 알아보면
위에 코드에서 적은대로 거의 메서드의 이름대로 되는걸 볼 수 있다.
그중에서 보자마자 이해가 안되는 메서드들에 대해서 보자
먼저 .keys()는 말그대로 key값을 알려주는것이다.
.entries()는 key-value를 출력하는것이지만
Set은 Key가 없기 때문에 [key,key]가 출력된다.

위크셋

위크셋은 세트와 유사하지만 객체만 포함한다.

WeakSet 객체는 객체 컬렉션입니다. WeakSet 내 객체는 오직 한 번만 발생할 수 있습니다. 즉, WeakSet 컬렉션 내에서 유일합니다.

위크셋은 이터러블이 아니다.

예제가 컴퓨터에서 실행이 안되고 이상하게 출력이된다.
다음기회에 자세하게 보는걸로..

맵은 set과 유사하지만 key-value 형태이다.
맵 메서드와는 다른 Map 객체이다.

const family = new Map();

family.set("Dad", 50);
family.set("mom", 40);
family.set("son", 20);

console.log(family);
console.log(family.size);

family.forEach((val, key) => console.log(key, val));

for (const [key, val] of family) {
    console.log(key, val);
}

출력결과
Map(3) { 'Dad' => 50, 'mom' => 40, 'son' => 20 }
3
Dad 50
mom 40
son 20
Dad 50
mom 40
son 20

0개의 댓글