오늘은 저의 생일입니다. 힘들지만 울고 있진 않아요(!) 나름대로 공부도 하고 축하도 많이 받고 행복한 하루를 보냈고! 무엇보다 지난주 강의에서 몹시 괴로운 나날을 보냈는데(..이게 뭐지의 연속 속에서) 오늘 2주차 강의를 듣기 시작했는데 너무 너무 재밌어서 와 뭐지?! 뭐지?! 너무 재밌는데?! 하면서 1일치를 다 들었습니다. 강사님이 이제 더 재밌는 구현을 해볼거예요. 하실 때마다 엥?! 더 재밌는 게 있다고?! 이미 이렇게 재미있는데?! 하면서 정말 강의가 호로록 흘러갔습니다.
HTML : 하이퍼 링크 + 마크 업 = HTML
HTML은 로직이 없고 수학적 계산을 할 수 없기 때문에 프로그래밍 언어라고 보기 어렵고 워드와 같은 문서 형태에 가깝다.
*마크업(Mark Up) : 실제 문서에 수정사항을 표시하는 것을 나타낸다.
HTML/CSS : 이전에는 HTML만으로 모든 문서의 뼈대와 양식을 만들었으나 점점 웹이 커질 수록 문서와 요소들은 많아지는데 수정 사항이 발생했을 때 비슷한 요소/문서들을 한 번에 수정하지 못 하고 일일이 수정해주어야 한다는 문제점이 생겼다.
그래서 이를 뼈대인 HTML과 스타일을 나타내줄 수 있는 CSS(Cascading Style Sheets)로 분리하게 되었고 HTML5(2014)에 오면서 HTML 문서 내에서 자체적으로 스타일을 표현해주는 태그들은 점차 사라지게 되었다. <center>
, s
, u
, font
등이 이에 속한다.
+) 지지난주 스터디 모임에서 퍼블리싱 강의를 해줄 때 채은이 CSS와 HTML을 구분해서 작성하게 된 이유가 뭐냐고 질문을 했었는데 이에 대해 아는 바가 없어서 답변을 명쾌하게 해주지 못 했는데 이걸 다음 모임 때 추가 답을 해줄 수 있을 거 같아 듣고 아!💡 했다.
*(참고) CSS 전체 스타일 삭제하기
*(참고) 모든 브라우저에서 동일한 스타일 양식 적용하기
*(참고) 웹페이지 스타일 어떻게 구현할지 막막할 때
+) DOM에 대한 설명도 들었으나 DOM과 DOM Element 탐색에 대해서는 어느 정도 익숙하기 때문에 따로 정리는 하지 않겠다. *DOM + CSSOM >> LENDER TREE
자바스크립트에서의 함수는 일급이기 때문에 함수를 값, 변수로서 다룰 수 있다.
*일급: 값으로 다뤄 변수에 담을 수 있으며 함수의 인자 및 결과로 사용 가능
기존에 ES5까지 우리는 어떤 배열이나 유사 배열인 문자열 안의 모든 요소들을 탐색하기 위해서는
const list = [1, 2, 3];
for (var i = 0; i < list.length; i++) {
console.log(list[i]);
}
이와 유사한 형태의 반복문을 통해서 구현해야만 했다.
그러나 ES6+ 에서는for ..of
를 통해서는
for (const a of list) console.log(a);
이렇게 간결하게 구현이 가능해졌다. 이 방식을 이용하면 array
, string
뿐만 아니라 set
, map
의 형태도 탐색이 가능하다. 그런데 for.. of
의 작동방식은 우리가 ES5까지 사용했던 for
를 통해 탐색하는 형태와 작동 방식이 동일할까? 답은 아니다.
console.log('Arr--------------');
const arr = [1, 2, 3];
for (const a of arr) console.log(a);
console.log(arr[Symbol.iterator]); // function values() { [native code] }
console.log('Set--------------');
const set = new Set([1, 2, 3]);
for (const a of set) console.log(a);
console.log(set[Symbol.iterator]); // function values() { [native code] }
console.log('Map--------------');
const map = new Map([['a', 1], ['b', 2], ['c', 3]]);
for (const a of map) console.log(a);
console.log(map[Symbol.iterator]); // function entries() { [native code] }
위 코드의 출력값들을 잘 기억해두자!
[Symbol.iterator]()
를 가진 값next()
메서드를 가진 값for..of
, 전개 연산자
등과 함께 동작하도록 하는 규약const arr = [1, 2, 3];
let iterator = arr[Symbol.iterator]();
console.log(iterator.next()); // {done: false, value: 1}
console.log(iterator.next()); // {done: false, value: 1}
console.log(iterator.next()); // {done: false, value: 1}
console.log(iterator.next()); // {done: true, value: undefined} // 동작 완료
위 코드의 출력 값을 보면 배열의 모든 요소의 순회를 끝내자 done: true
로 변경되는 것을 알 수 있고 이것이 왜 기존에 사용하던 for
문과 배열의 index를 이용한 순회와 다른지 알 수 있다. 여기서 .next()
메서드는 다음과 같이 작동한다.
const arr = [1, 2, 3];
let iter1 = arr[Symbol.iterator]();
iter1.next();
for (const it of iter1) console.log(it); // 2, 3만 출력됨
const set = new Set([1, 2, 3]);
let iter1 = set[Symbol.iterator]();
iter1.next();
for (const a of iter1) console.log(a); // 2, 3만 출력됨
const map = new Map([['a', 1], ['b', 2], ['c', 3]]);
let iter1 = map[Symbol.iterator]();
iter1.next()
for (const a of iter1) console.log(a); // ["b", 2], ["c", 3]
잘 구현된(well-formed) 이터러블은 이렇게 순회를 하면서 출력할 수 있고 그 앞에 .next()
같은 동작을 추가해주더라도 다음 iterator로 넘어가서 순회를 계속할 수 있다. 그 안에 다른 이터러블을 넣어준다고 하더라도 정상적으로 작동하며 순회한다.
제너레이터 함수를 선언할 때는 우리가 JS에서 일반적으로 함수를 선언할 때 사용하는 형태에서 함수 이름에 '*'을 추가해주어야 하며 yield
라는 키워드를 함께 사용할 수 있다.
// 일반 함수
function normal(var1, var2) {
stack.push(var1);
stack.push(var2);
console.log(stack);
}
// 제너레이터
function *gen(var1, var2) {
yield var1;
yield var2;
}
generator는 well formed iterator를 생성하는 함수라고 한다. 자바스크립트에서는 어떠한 값이든 이터러블이면 순회할 수 있는데 제너레이터는 이런 문장을 값으로 만들 수 잇고 이런 문장을 통해서 순회할 수 있는 값을 만들 수 있기 때문에 자바스크립트에서 이 제너레이터를 통해 어떠한 상태나 값이든 사실상 순회할 수 있게 만들 수 있단 이야기가 되기 때문에 상징적이라고 한다. 또한 함수형 프로그래밍에서 가장 중요한 부분이라고도 할 수 있다.
// 수를 무한대로 생성하는 제너레이터
function *infinity(i = 0) {
while(true) yield i++;
}
// limit 값을 설정하는 제너레이터
function *limit(l, iter) {
for (const a of iter) {
yield a;
if (a == l) return;
}
}
// 짝수값만 생성하는 제너레이터
function *even(l) {
for (const f of limit(l, infinity(1))) {
if (f % 2 == 0) yield f;
if (f == l) return;
}
}
for (const a of even(40)) console.log(a);
console.log(...even(10));
console.log([...even(10), 'even(10) end', ...even(20)]);
const [head, ...tail] = even(6);
console.log(head); // 2
console.log(tail); // 4, 6 // ...tail : head 이후 tail 끝까지
const [a, b, ...rest] = odds(10);
console.log(a); // 2
console.log(b); // 4
console.log(rest); // 6, 8, 10