2021.05.02
소스코드: response-check.html

HTML에서 요소에 대한 정보를 저장할 때가 있으니 최대한 이것을 활용하자.
클래스명을 사용하기: 태그에 해당 클래스가 들어있는지는 TAG.classList.contains('클래스'); = T/F로 찾을 수 있다.
$screen.addEventListener("click", (event) => {
if (event.target.classList.contains("waiting")) {
$screen.classList.remove("waiting");
$screen.classList.add("ready");
$screen.textContent = "초록색이 되면 클릭하세요";
setTimeout(() => {
let startTime = new Date(); // 선언
$screen.classList.remove("ready");
$screen.classList.add("now");
$screen.textContent = "클릭하세요!";
}, Math.floor(Math.random() * 1000) + 2000);
} else if (event.target.classList.contains("ready")) {
} else if (event.target.classList.contains("now")) {
let endTime = new Date(); // 선언
result = endTime - startTime;
$result.textContent = `${result}ms`;
$screen.classList.replace("now", "waiting");
$screen.textContent = "클릭해서 시작하세요.";
}
});
$screen.addEventListener("click", (event) => {
let startTime; // 선언
let endTime; // 선언
if (event.target.classList.contains("waiting")) {
$screen.classList.remove("waiting");
$screen.classList.add("ready");
$screen.textContent = "초록색이 되면 클릭하세요";
setTimeout(() => {
startTime = new Date(); //호출
$screen.classList.remove("ready");
$screen.classList.add("now");
$screen.textContent = "클릭하세요!";
}, Math.floor(Math.random() * 1000) + 2000);
} else if (event.target.classList.contains("ready")) {
} else if (event.target.classList.contains("now")) {
endTime = new Date(); //호출
result = endTime - startTime;
$result.textContent = `${result}ms`;
$screen.classList.replace("now", "waiting");
$screen.textContent = "클릭해서 시작하세요.";
}
});
let startTime; // 선언
let endTime; // 선언
$screen.addEventListener("click", (event) => {
if (event.target.classList.contains("waiting")) {
$screen.classList.remove("waiting");
$screen.classList.add("ready");
$screen.textContent = "초록색이 되면 클릭하세요";
setTimeout(() => {
startTime = new Date(); //호출
$screen.classList.remove("ready");
$screen.classList.add("now");
$screen.textContent = "클릭하세요!";
}, Math.floor(Math.random() * 1000) + 2000);
} else if (event.target.classList.contains("ready")) {
} else if (event.target.classList.contains("now")) {
endTime = new Date(); //호출
result = endTime - startTime;
$result.textContent = `${result}ms`;
$screen.classList.replace("now", "waiting");
$screen.textContent = "클릭해서 시작하세요.";
}
});
const
const a = "123";
a = "456";
//result
//Uncaught TypeError: Assignment to constant variable...
const array = [1, 2, 3];
array.push(4);
console.log(`${array}`);
// result
// [1,2,3,4]
array = [1, 3, 5];
//result
//Uncaught TypeError: Assignment to constant variable...
const를 사용하면 해당 변수를 대입할 수 없다.
그러므로 const 변수명 = 초기값;으로 했을 때, 아래에 변수명 = 대입값;이라는 단순 참조를 할 수 없다.
ES6(ES2015)이전에는 변수를 선언할 수 있는 키워드가 var뿐이었다.
하지만 ES6에서는 let, const 키워드가 추가되어 이를 이용해서도 변수를 선언할 수 있게 됐다.
var, let, const의 차이
2번의 경우를 보면 ‘그럼 var는 호이스팅이 되고 let, const는 호이스팅이 안되기 때문에 그러는건가?’ 라고 생각할 수 있는데, 그렇지 않다.
자바스크립트에서 사용하는 var, let, const, function, class 등의 선언 키워드들은 모두 호이스팅이 된다.
var의 경우 호이스팅되면서 초기 값이 없으면 자동으로 undefined를 초기값으로 하여 메모리를 할당한다. 그래서 var의 경우 선언 전에 해당 변수를 사용하려고 해도 메모리에 해당 변수가 존재하기 때문에 에러가 발생하지 않는다.
console.log(num); // undefined
var num;
그런데 let, const의 경우 호이스팅이 되면서 초기 값이 없다면 var처럼 자동으로 초기값을 할당하지 않는다. (const의 경우 선언시 초기값을 할당하지 않으면 Syntax에러 발생). 그래서 값이 할당되기 전까지 메모리를 할당하지 않기 때문에 선언 전에 (정확히는 값이 할당되기 전에) 사용하려고 하면 메모리에 해당 변수가 존재하지 않아 에러를 발생시킨다.
이처럼 변수가 선언되고 해당 변수에 값이 할당되기 전까지(2024.07.02: 스코프의 시작 지점부터 초기화 시작 지점까지의 구간)를 TDZ(Temporal Dead Zone)라고 한다.(2024.07.02: TDZ 개념 다시 한번 읊고 간다.)
console.log(num); // Uncaught ReferenceError: num is not defined
let num = 1;
console.log(num); // 1
// 호이스팅 되었을 때
let num;
console.log(num); // 값이 할당되기 전이므로 아직 num은 메모리에 존재하지 않음. TDZ.
num = 1;
console.log(num); // 1
5번의 경우 const로 선언한 변수에 객체를 할당했을 때 const 변수가 가리키고 있는 객체 자체를 변경하는 것은 불가능하지만 해당 객체 내의 프로퍼티가 변경되는 것까지 막는다는 것은 아니다. 아래의 코드를 보자.
const obj = { first: 1 };
// 에러 발생
obj = 1; // Uncaught TypeError: Assignment to constant variable.
// 에러 발생하지 않음.
obj.first = 2;
obj.second = 2;
delete obj.first;
위와 같이 const 변수가 가리키는 값 자체를 변경하려고 하면 에러가 발생하지만 객체 내의 프로퍼티의 추가, 변경, 삭제를 하는 것은 문제가 없다. 만약 객체의 프로퍼티도 변경되지 않게 객체를 선언하고 싶으면 Object.freeze() 메소드를 사용할 수 있다(Object.freeze()는 얕은 동결이기 때문에 객체 내의 또다른 객체의 프로퍼티 변경까지 동결하지는 못한다).
결론: var의 경우 버그 발생과 메모리 누수의 위험 등이 있기 때문에 var말고 let, const를 사용하는 것이 좋다.
[1, 2, 3, 4].reduce((a, c) => a + c, 0);
// a는 누적값, c는 현재값, a+c는 다음 누적값, 0은 초기값.
// a:0 c:1
// a:1 c:2
// a:3 c:3
// a:6 c:4
// 10
위와 같이 배열명.reduce((누적값인자, 현재값인자, 다음 인덱스) => (리턴하는 다음 누적값), 초기값); 형식으로 작성할 수 있으며, 뜻 그대로 여러개의 배열요소를 하나의 값으로 축소해주는 역할을 한다.
정석은 아래와 같다.
배열. reduce((누적값,현재값)=>{
return 새로운 누적값;
}, 초기값);
그래서 평균을 구하고 싶으면 [1,2,3,4].reduce((a,c)=>(a+c),0) / [1,2,3,4].length (누적값/배열길이)로 표현이 가능하다.
초기값이 없으면 배열 0 index의 1이 초깃값이 된다. 초깃값은 첫 번째 누적값으로 들어가기 때문에 이때는 두 번째 요소부터 reduce를 적용하게 된다. 따라서 누적값(a) 1, 현재값(c) 2인 상태로 함수가 시작된다. 반환값인 3은 다음 번의 누적값이 된다.
또한 이렇게도 가능하다.
['철수','영희','민초','하와이안'].reduce((a,c,i)=>{a[i]=c; return a},{});
result
{0:'철수', 1:'영희', 2: '민초', 3:'하와이안'}
a:{}, c:'철수', i:0
a:{0:'철수'}, c:'영희', i:1
a:{0:'철수', 1:'영희'}, c:'민초', i:2
a:{0:'철수', 1:'영희', 2:'민초'}, c:'하와이안', i:3
a:{0:'철수', 1:'영희', 2:'민초', 3:'하와이안'}
reduce로 객체 리터럴 생성이 가능한 것을 볼 수 있다. 중요한건 초기값을 무엇으로 했는지 잘 봐야한다. map과 reduce는 가장 중요한 개념이기에 반드시 숙지해야 한다. + 실행컨텍스트와 promise, 이벤트루프만 마스터하자.2024.07.02
T-learning은 내가 믿고 있는 원칙이다. 필자는 비록 현재 react-native를 현업에 사용중이지만, iOS 개발자로 전향할 준비를 하는 중이다.