컴퓨터 과학에서, 함수를 변수와 동일하게 다루는 프로그래밍 언어를 일급 함수를 가졌다고 언급한다. 이것은 언어가 함수를 다른 함수에 인자로 전달하고, 다른 함수의 값으로 반환하고, 변수에 할당하거나 데이터 구조에 저장하는 것을 지원한다는 것을 의미한다.
function sayHello() {
return "Hello, ";
}
function greeting(helloMessage, name) {
console.log(helloMessage() + name);
}
// `sayHello`를 `greeting` 함수에 인자로 전달
greeting(sayHello, "JavaScript!");
function sayHello() {
return function() {
console.log("Hello!");
}
}
const add10 = a => a + 10;
console.log(add1)
// 함수의 내용이 나온다 즉, 변수에 함수가 담겼다로 생각할 수 있다.
const times = (f, n) => {
let i = 0;
while(i < n) {
f(i++);
}
}
times(console.log, 3);
const addMaker = a => b => a + b; // 커링??
const add10 = addMaker(10);
console.log(add10);
iterable인 것은 어떻게 순회할지에 대해 구체적, 명령적으로 정의하기 보다는 보다 선언적으로 정의하여 순회할 수 있다.
const str = 'abc';
// 어떻게 순회할지에 대해 구체적, 명령적으로 정의하기 보다는
for(let i = 0; i < str.length; i+=1) {
// console.log(str[i]);
}
// 보다 선언적으로 가능해짐
for(const i of str) {
// console.log(i);
}
map 의 경우에는 for... of문 내부에서 keys(), values() 메서드로 호출하여도 다시 iterable한 객체를 반환해줌.
아래와 같은 코드가 가능해짐
const map = new Map([['a', 1], ['b', 2]]);
for(const a of map.keys()) console.log(a);
DOM과 관련된 값들도 Iterable 값을 가짐
for(const a of document.querySelectorAll('*')) console.log(a);
Well-formed iterable의 추가적인 조건
iterator 객체 또한 Symbol.iterator 메소드가 존재하며, iterator 객체인 자기 자신을 반환하는 것
const countObj = {
from: 1,
to: 5,
}
Object.defineProperty(countObj, Symbol.iterator, {
value() {
let {from, to} = this;
return {
next() {
if(from <= to) return iteratorProtocol(from++);
return iteratorProtocol();
},
[Symbol.iterator]() {return this}
}
}
})
function iteratorProtocol(value) {
if(!value) return { done: true };
return {
done: false,
value
}
}
for(const a of countObj) {
console.log(a);
}
제네레이터 함수에 의해 반환되며 이전 시간에 배운 Iterable Protocol과 Iterator Protocol을 준수하는 객체
그렇기 때문에 아래와 같이 반복이 가능
function *gen() {
yield 1;
yield 2;
yield 3;
}
for(const a of gen()) console.log(a);
제네레이터 함수에 의해 반환되는 Generator가 Iterable Protocol을 준수하는 객체라고 했던 이유가 Generator가 Iterator 객체이기도 하지만 잘 만들어진 Iterator는 또 다시 자신을 반환하는 Well-formed iterable이기 때문이다.
const wellFormedIterable = {
[Symbol.iterator](){
return {
next() { }, // 생략
[Symbol.iterator]() { return this; } // 이 부분!!!
}
}
}