파게로그
33 Concepts Every JS Developer Should Know 본문
const result = add(10, 20);
const add = (a, b) => a+b;
console.log(result); // error
JS 개발자 사이에서는 하나의 성경과 같은 것을 발견했다.
https://github.com/leonardomso/33-js-concepts
한국어 버전은 이건데, 번역이 되어 있는 건 아니고 영어로 된 영상만 링크를 건 것 같다.
https://github.com/yjs03057/33-js-concepts
어쨌든, 몇 가지 헷갈리는 개념들이 있어서 정리해 보았다.
#1. undefined vs null vs NaN
undefined: not defined yet
null: defined as 'not exist'
NaN: not a number
let sth;
console.log(sth); // undefined
let nullConst = null;
console.log(nullConst); // null
let wtf = Math.power(5, "hi");
console.log(wtf); // NaN
#2. Value types vs Reference types
call by value: string, number, boolean, undefined, null, NaN
call by reference: array, object, function
console.log([10]===[10]); // false
#3. Type Coercion(feat. == and ===)
Javascript converts type of value forcibly when == used.
If === used, type coercion does not happen.
console.log("1"==1); // true
console.log("1"===1); // false
console.log("1"==true); // true (== converts boolean to number)
console.log("true"==true); // false ("true" cannot be converted to number)
console.log(10+true); // 11 (true: 1, false: 0)
console.log(0==false); // true
console.log(10+"true"); // 10true (loaded operator?)
console.log(5+10+"true"); // 15true (read left to right)
console.log(10-"1"); // 9 (parse to integer)
console.log(undefined==true); // false
console.log(undefined==false); // false
console.log(null==true); // false
console.log(null==false); // false
console.log(NaN==true); // false
console.log(NaN==false); // false
if ("") {console.log("executed");} // nothing displayed
if ("hi") {console.log("executed");} // hi
#4. typeof
typeof(1) // number
typeof 1 // number
중대한 버그가 있다.
참고로 typeof
는 primitive type에, instanceof
는 Array, Object에 사용한다.
const sthArr = [1, 2, 3];
const sthObj = {name: "Nancy", height: 165};
console.log(typeof(sthArr)); // object
console.log(typeof(sthObj)); // object
// to tell apart array and object
console.log(sthArr instanceof Array); // true
console.log(sthArr instanceof Object); // false
console.log(sthObj instanceof Array); // false
console.log(sthObj instanceof Object); // true
#5. Scope
let
, const
는 block scope!var
는 funciton scope... 사용을 지양하자.
#6. Expression vs Statement
Expression: value를 return하는 무언가.
Statement: variable에 assign될 수 없음(=는 expression을 기대하고 있음).
참고로 hoisting이란 모든 declaration을 상단으로 가져오는 것이다.
물론 아래는 불가능하다.
const result = add(10, 20);
function add(a, b) {
return a+b;
}
console.log(result);
#7. IIFE, Modules and Namespaces
IIFE
IIFE: Immediately-Invoked Function Expression
예를 들어, 어떤 array는 클라이언트가 브라우저에서 읽거나 수정할 수 있다.
기능은 수행되도록 하되 클라이언트로부터의 접근을 차단하려면 IIFE에 넣는다.
(function() {
const secretUsers = ["David", "Alice", "Jenny"];
console.log(secretUsers);
})();
// 출력은 가능하지만 console에서 secretUsers를 입력하면 undefined
(() => {
const secretUsers = ["David", "Alice", "Jenny"];
console.log(secretUsers);
})();
// 조금 더 나은 디자인
Module
webpack, gulp 등 모듈 번들러 없이, 바닐라 자바스크립트로 모듈 합치기를 어떻게 할 수 있을까?
HTML에서 js 파일이 모듈이라고 말해준다!
<script type="module" src="app1.js"></script>
<script type="module" src="app2.js"></script>
app1.js, app2.js는 각각 다음과 같다.
/* app1.js */
export let users = ["Stephanie", "Aiden", "Logan"];
export const addUser = (user) => users = [...users, user];
// users = [...users, user]
// 이 방식은 값을 돌릴 수 없는 immutable 방식임.
// push를 할 수도 있지만 Nicolas가 함수형 프로그래밍에 꽂혀 있어서 그랬다고 함...
export const getUsers = () => users;
export const deleteUser = (user) => users = users.filter(aUser => aUser !== user);
/* app2.js */
import {users, addUser, getUsers} from "./app1.js";
console.log(getUsers());
addUser("Autumn");
console.log(getUsers());
// 브라우저는 원래 import, export를 이해하지 못하기 때문에 error를 띄움
// 하지만 ES6부터는 HTML에서 모듈임을 말해준다면 정상 실행
#8. Message Queue and Event Loop
먼저, blocking 언어와 non-blocking 언어가 있다.
예를 들어 Python은 blocking 언어, JS는 non-blocking 언어이다.
만약 JS가 blocking 언어였다면, 우리는 input에 타이핑을 할 수가 없는데,
JS는 API fetch를 핸들링하느라 바빴을 것이기에 그렇다.
즉 user input, event, fetch 등 무엇이든 한 번에 하나밖에 못하니까.
자세한 개념은 다음의 두 링크를 참고하자.
http://homoefficio.github.io/2017/02/19/Blocking-NonBlocking-Synchronous-Asynchronous/
https://heecheolman.tistory.com/48
다만, 예를 들어 alert는 blocking function이다. 창 뜨면 아무것도 못한다.
alert("Alert!");
console.log("hi");
본론으로 돌아와서, 다음과 같은 코드에서 괄호에 넣은 것들은 어디로 가는 것일까?
setTimeout(console.log, 0, "hi");
console.log("bye");
// bye 출력 후 hi 출력
Web API는 JS가 default로 가지고 있지 않은, localStorage, setTimout 등의 기능을 수행한다.
fetch의 경우에도 Web API가 웹 사이트를 부르고, 메시지가 Queue로 오고,
그 후 JS가 준비되었을 때 Queue에서 불러서 함수를 실행시킴.
callback, event 등이 있는 건... non-blocking 언어니까 timeout 같은 것을 넣을 곳이 필요하기 때문이다.
setTimout에 대한 설명에서 알 수 있듯, time specific하지 않다.
한편 다음과 같은 코드로 setTimeout이나 setInterval에 대한 취소가 가능하다.
const hiT = setTimeout(console.log, 10000, "hi");
console.log(hiT); // ID of Timeout is displayed.
clearTimeout(hiT); // cancel
const helloT = setInterval(console.log, 5000, "hello");
console.log(helloT);
clearInterval(helloT); // cancel
// clearTimeout()이나 clearInterval()에 잘못된 인자가 들어가도 에러가 발생하지는 않는다.
#8. requestAnimationFrame
animation
사람들은 지금까지 스크린에서 뭔가 움직이게 하려면 setInterval을 사용했다.
하지만 setInterval은 time specific하지 않고, 그리고 CPU나 GPU에 따라서 interval이 늘어날 수 있기에 나빴다.
그러나 requestAnimatioFrame은 브라우저를 다시 렌더링하기 전에 함수를 실행한다.
브라우저가 업데이트 할때마다 animation frame을 요청할 거고, 그래서 애니메이션을 수정할 수 있다.
CPU랑 그래픽카드에 최적화되어 있어서, 다른 탭으로 이동하면 Chrome은 이걸 실행시키지 않는다.
해당 스크린을 페인트하는 게 아니니까! 즉, 뭔가를 최대한 빠르게 실행하고 싶을때 사용한다.
requestAnimationFrame(() => console.log("hi"));
// callback은 브라우저 렌더링 이전에 호출된다.
const sayHi = () => {
console.log("hi");
requestAnimationFrame(sayHi);
};
requestAnimationFrame(sayHi);
아직 몇 가지 이해되지 않는 부분들은 추가로 검색해보고 보충해두어야겠다.
'콤퓨타 왕기초 > JS' 카테고리의 다른 글
유용한 libs, APIs (0) | 2020.10.15 |
---|---|
JSON 다루기 (0) | 2020.10.15 |
DOM에서 element 생성 또는 제거 (0) | 2020.10.15 |
array (0) | 2020.10.15 |
event, event handlers (2) (0) | 2020.10.12 |