일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- Git
- 문자열보간법
- useMemo
- styled-components install error
- 너무무서워
- 기본데이터타입
- 샐러드좋아
- 정처기
- 취미
- 서브웨이
- 전복과붕어빵
- ERESOLVE
- javascript
- 커링
- GitLab
- 러닝자바스크립트
- 상수와변수
- 아이행복해
- 오늘양짱많음
- node version update
- 프라모델
- 자고싶다
- 노드 버전
- 찐대졸
- 카드지갑
- 가죽공예
- 내일의주인공은나야나
- 후록스
- 로스트치킨샐러드
- 면담끝
- Today
- Total
당근농장
[Learning JavaScript] 객체와 객체지향 프로그래밍 / 이터레이터와 제너레이터 / 함수와 추상적 사고 본문
[Learning JavaScript] 객체와 객체지향 프로그래밍 / 이터레이터와 제너레이터 / 함수와 추상적 사고
devcarrot 2022. 9. 23. 20:539장. 객체와 객체지향 프로그래밍
9.2.3 프로토타입
동적 디스패치
메서드 오버라이딩이 되어 있는 경우 실행 시점에 어떤 메서드를 실행할 지 결정되는 것.
객체의 프로퍼티나 메서드에 접근하려 할 때 그런 프로퍼티나 메서드가 존재하지 않으면 자바스크립트는 객체의 프로토타입에서 해당 프로퍼티나 메서드를 찾는다. 클래스의 인스턴스는 모두 같은 프로토타입을 공유하므로 프로토타입에 프로퍼티나 메서드가 있다면 해당 클래스의 인스턴스는 모두 그 프로퍼티나 메서드에 접근할 수 있다.
디스패치
: 메서드 호출과 같은 의미
9.2.5 상속
프로토타입 체인
객체의 프로토타입에서 메서드를 찾지 못하면 자바스크립트는 프로토타입의 프로토타입을 검색한다. 즉, 조건에 맞는 프로토타입을 찾을 때까지 프로토타입 체인을 계속 거슬러 올라가고, 조건에 맞는 프로토타입을 찾지 못하면 에러를 일으킨다.
12장. 이터레이터와 제너레이터
이터레이터
지금 어디 있는지 파악할 수 있도록 돕는다는 면에서 일종의 책갈피와 비슷한 개념.
이터레이터의 next 메서드를 호출하면 value 프로퍼티(지금 어디 있는지)와 done 프로퍼티(마지막 값을 읽으면 true로 바뀌는)가 있는 객체를 반환한다. next에서 마지막 값을 반환했다 하더라도 끝난 것은 아니다. 더 진행할 것이 없으면 value는 undefined가 되지만(done도 계속 true), next는 계속 호출할 수 있다.
for...of 루프가 인덱스 없이 루프를 실행할 수 있는 이유는 이터레이터 덕분이다. 즉, 이터레이터만 제공할 수 있다면 무엇이든 for…of 루프와 함께 쓸 수 있다.
12.1 이터레이션 프로토콜
이터레이션 프로토콜은 데이터 컬렉션을 순회하기 위한 프로토콜(미리 약속된 규칙)이다. 이터레이션 프로토콜을 준수한 객체는 for…of 문으로 순회할 수 있고 Spread 문법의 피연산자가 될 수 있다. 이터레이션 프로토콜에는 이터러블 프로토콜(iterable protocol)과 이터레이터 프로토콜(iterator protocol)이 있다.
클래스에 심볼 메서드 Symbol.iterator가 있고, 이 메서드가 이터레이터처럼 동작하는 객체(value와 done 프로퍼티가 있는 객체를 반환하는 next 메서드를 가진 객체)를 반환한다면 그 클래스의 인스턴스는 이터러블 객체라는 뜻이다.
12.2 제너레이터
제너레이터란 이터레이터를 사용해 자신의 실행을 제어하는 함수이다. 일반적으로 함수를 호출하면 그 함수가 종료될 때까지 제어권을 완전히 넘기는 것이지만, 제너레이터에서는 그렇지 않다.
제너레이터는 두 가지 예외를 제외하면 일반적인 함수와 같다.
- 제너레이터는 언제든 호출자에게 제어권을 넘길(yield) 수 있다.
- 제너레이터는 호출한 즉시 실행되지 않는다. 대신 이터레이터를 반환하고, 이터레이터의 next 메서드를 호출함에 따라 실행된다.
12.2.1 yield 표현식과 양방향 통신
제너레이터와 호출자 사이에서 yield 표현식을 이용하면 양방향 통신이 가능하다. yield 표현식의 값은 호출자가 제너레이터의 이터레이터에서 next를 호출할 때 제공하는 매개변수가 된다.
12.2.2 제너레이터와 return
yield 문은 설령 제너레이터의 마지막 문이더라도 제너레이터를 끝내지 않는다. 제너레이터에서 return 문을 사용하면 그 위치와 관계없이 done은 true가 되고, value 프로퍼티는 return이 반환하는 값이 된다.
하지만 제너레이터를 사용할 때는 done이 true이면 value 프로퍼티를 잘 신경쓰지 않으므로 중요한 값을 return으로 반환하는 것은 지양해야 한다. 제너레이터가 반환하는 값을 사용하려 할 때는 yield를 써야 하고, return은 제너레이터를 중간에 종료하는 목적으로만 사용해야 한다.
function* abc() {
yield 'a';
yield 'b';
return 'c';
}
// "a"와 "b"는 출력되지만 "c"는 출력되지 않는다.
for(let l of abc()) {
console.log(l);
}
13장. 함수와 추상적 사고
13.1 서브루틴으로서의 함수
함수의 이름을 정하는 건 굉장히 중요한 일이다. 함수의 이름은 자바스크립트를 위한 것이 아니고, 다른 사람 또는 나중에 이 코드를 다시 볼 나를 위해 정하는 것이다. 따라서 함수의 이름을 정할 때는 다른 사람이 함수 이름만 봐도 함수에 대해 이해할 수 있도록 주의 깊게 생각해야 한다.
13.3 함수로서의 함수
순수 함수(pure function)
부수 효과(side effect)가 없는 함수. 즉, 어떤 함수에 동일한 입력을 주었을 때 항상 같은 결과를 반환하는 함수이다. 그렇기에 코드를 테스트하기 쉽고, 이해하기 쉽고, 재사용하기가 더 쉬워진다는 장점이 있다.
부수 효과
: 외부의 상태를 변경하는 것 또는 함수로 들어온 인자의 상태를 직접 변경하는 것
함수가 상황에 따라 다른 값을 반환하거나 부작용이 있다면 그 함수는 컨텍스트에 좌우되는 함수이다. 어떤 함수가 정말 유용하더라도 부수 효과가 있다면, 그리고 그 함수가 쓰이던 프로그램이 아닌 프로그램에서 사용하려 한다면 문제를 일으킬 수 있다.
99%는 제대로 동작하다가 1%의 상황에서 버그를 일으키는 경우는 오랫동안 발견되지 않기 때문에 문제가 있다는 걸 알게 되더라도 찾기가 정말 어려워진다. 따라서 항상 순수 함수를 쓰는 습관을 들이는 것이 좋다.
순수 함수로 변경
외부 변수를 바꾸는 부수 효과가 있는 경우, 부수 효과를 없애기 위한 가장 쉬운 방법은 외부 변수를 클로저로 감싸는 것이다. 하지만 이러한 경우에도 프로그램의 다른 부분에서 같은 함수를 호출한다면 부수 효과가 생기는 경우가 존재한다.
이런 경우, 이터레이터를 사용하면 해당 함수는 항상 같은 것(이터레이터)을 반환하며 외부에 아무 영향도 주지 않게 된다. next()는 함수가 아닌 메서드기 때문에 자신이 속한 객체라는 컨텍스트 안에서 동작하여 메서드의 동작은 그 객체에 의해 좌우된다. 따라서 프로그램의 다른 부분에서 함수를 호출하더라도 독립적인 이터레이터가 생성되므로 다른 이터레이터를 간섭하지 않는다.
13.5 IIFE와 비동기적 코드
스코프(scope)
변수에 접근할 수 있는 범위
- 전역(global) 스코프
전역이란 코드의 가장 바깥쪽 영역을 의미하며, 전역에 변수를 선언하면 전역 스코프를 갖는 전역 변수가 되고 어느 곳에서든지 해당 변수에 접근이 가능하다. - 지역(local) 스코프
지역이란 함수 몸체 내부를 의미하며, 지역에 변수를 선언하면 지역 스코프를 갖는 지역 변수가 되고 자신의 지역 스코프 또는 하위 지역 스코프에서만 접근할 수 있어 지역을 벗어난 곳에서는 접근할 수 없다.
함수 스코프와 블록 스코프
지역 스코프에는 함수 스코프와 블록 스코프가 있으며, 자바스크립트는 기본적으로 함수 스코프를 따르는 언어이다. 하지만 let과 const 키워드의 등장으로 블록 스코프를 형성하는 것도 가능해졌다.
- 함수 스코프
함수가 선언되면 하나의 스코프가 발생하는데, 이를 함수 스코프라고 한다. 함수에서 선언한 변수는 해당 함수 내에서만 접근 가능하다. - 블록 스코프
블록({})이 생성될 때마다 새로운 스코프가 발생하는데, 이를 블록 스코프라고 한다. 블록 내부에서 선언된 변수는 해당 블록에서만 접근 가능하다.
function loop() {
for (let i=0; i<5; i++) {
console.log(i);
}
console.log(i);
}
loop(); /* ReferenceError: i is not defined */
for문 내에서 i를 let으로 선언한 순간 i는 for문 내에 종속되며, for문 외부에서는 i에 접근할 수 없다. 만약 여기서 let이 아닌 var를 사용하면 해당 코드는 에러를 일으키지 않는다.
for (let i=5; i>=0; i--) {
setTimeout(function() {
console.log(i===0 ? "go!" : i);
}, (5-i)*1000);
}
또한, let 키워드를 이런 식으로 사용하면 자바스크립트는 루프의 단계마다 변수 i의 복사본을 새로 만든다. 따라서 setTimeout에 전달한 함수가 실행될 때는 독립 스코프에서 변수를 받아 정상적으로 타이머가 동작한다. 만약 여기서 let을 사용하지 않는다면 루프의 i가 -1이 되어 끝나기 전에는 콜백 함수가 전혀 호출되지 않으므로 -1만 출력된다.
13.6.3 함수를 반환하는 함수
커링
커링은 하나 이상의 매개변수(Parameter)를 갖는 함수를 부분적으로 나누어 각각 단일 매개변수를 갖는 함수로 설정하는 기법이다. 이를 이용하면 아래와 같이 단일 매개변수를 받으면서도 원하는 중간 함수를 마음대로 사용하는 것이 가능하다.
function sum(arr, f) {
if (typeof f != 'function') f = x +> x;
return arr.reduce((a, x) => a += f(x), 0);
}
function newSummer(f) {
return arr => sum(arr, f);
}
const sumOfSquares = newSummer(x => x*x);
const sumOfCubes = newSummer(x => Math.pow(x, 3));
sumOfSquares([1, 2, 3]); // 14
sumOfCubes([1, 2, 3]); // 36
func(a, b, c) → f(a)(b)(c)
위 식을 코드로 변경하려면 함수를 반환하는 함수를 작성하는 것이 필요하며 대략적인 코드를 작성하면 아래와 같다.
// non-curried
function sum(a, b, c) {
return a + b + c;
}
// curried
function sum(a) {
return function(b) {
return function(c) {
return a + b + c;
}
}
이런 식으로 사용하면 재사용이 가능해지며 생산성 및 가독성 향상에도 도움이 될 수 있다. 하지만 함수가 깊이 중첩되면 메모리를 과다하게 점유할 가능성이 있는 것과 같은 맥락에서 커링을 과용하면 메모리와 속도에 문제점 발생 가능성이 있다.
출처:
https://sosocodingday.tistory.com/122
[JavaScript] 스코프(scope)
1. 스코프란? 스코프는 자바스크립트를 포함한 모든 프로그래밍 언어의 기본적이며 중요한 개념이다. 모든 식별자(변수 이름, 함수 이름, 클래스이름 등)는 자신이 선언된 위치에 의해 다른 코드
sosocodingday.tistory.com
https://ko.javascript.info/currying-partials
커링
ko.javascript.info
https://choonse.com/2022/01/17/657/
쉽고 빠르게 커링(Currying) 기법 이해하기(feat.자바스크립트) - WORLD IS WIDE
커링은 하나 이상의 매개변수(Parameter)를 갖는 함수를 부분적으로 나누어 각각 단일 매개변수를 갖는 함수로 설정하는 기법입니다. 커링에 장단점과 사용법에 대해 알아보겠습니다.
choonse.com
'개발 > JavaScript' 카테고리의 다른 글
[JavaScript] 문자열 자르기 - substr(), substring(), slice() (0) | 2021.10.28 |
---|---|
JavaScript reduce() (1) | 2021.02.23 |