자바스크립트 문법을 이제 막 배웠고 오늘은 걸음마를 떼기 위한 시작점으로
개념을 정리 할 수 있도록 10개의 문제를 풀도록 했다.
해결해야 할 자바스크립트 파일의 수는 10개지만 한 파일에 몇가지 문제가 모여있고
총 통과해야할 테스트는 50가지였다.
페어분과 함께 논의하는 과정을 통해 빠른 시간 안에 모든 테스트를 통과 할 수 있었다.
간단한 문제처럼 보였지만 헷갈리는 부분도 있었고 이해 가지 않는 답이 나올 때는 페어님과
머리를 맞대고 도대체 왜 답이 이렇게 출력되는지에 대해 확실히 머릿속에 새길 수 있도록 서로 설명하고 이해하면서 문제를 풀어나갔다.
스스로 이해했다고 주장하며 정리하지만 머리속에서 증발 될 것이기 때문에
이번 과제를 통해 자바스크립트의 핵심 문법을 나의 언어로 정리해서
증발 될 때 마다 이 글을 참고하려고 한다 :)
자바스크립트에서 테스트 하는 값과 기대값을 비교하기 위해 사용하는 함수이다.
expect(테스트하는값).기대하는조건 // 기대하는조건'에 해당하는 함수를 matcher라고 함.
expect(muscleUp(protein)).to.be.true;
// => "muscleUp(protein)의 결과값은 참(ture)이어야 한다."
let protein = 100;
let carbohydrate = 50 + 50;
expect (protein === carbohydrate).to.be.true
// protein === carbohydrate와 값이 같으므로 expec함수가 기대하는 조건과 부합.
// 동치연산자 사용 시 == 사용하지 않게 주의expect('테스트하는값').to.equal('기대하는값'); <예시>expect(1 + 2).to.equal(3)
// sum(1, 2)의 결과값은 3과 같아야(equal) 한다
let a = (1+1).toString();
expect(a).to.equal(2); // 오류 .equal에 있는 2는 type이 number이기 때문
expect(a).to.equal("2") // 정답
it(function () {
let expectedValue = 1 + 1;
expect(1 + 1).to.equal(expectedValue);
}); // ture
.to.deep.equal
배열의 요소나 객체의 속성이 서로 같은지 확인하는 matcher
💡 equal과 deep equal의 차이deep equal은 객체 내부까지 비교해서 일치여부를 체크하는 메소드이다.
- 사용법 expect('테스트하는값').to.deep.equal('기대하는값');
<예시>
const overTwenty = ['hongsik', 'minchul', 'hoyong'];
let allowedToDrink = overTwenty;
overTwenty.push('san');
expect(allowedToDrink).to.deep.equal(['hongsik', 'minchul', 'hoyong','san']);
// => to.deep.equal은 배열의 요소나 객체를 비교할 수 있다.
• var는 function-scoped이고, let, const는 block-scoped이다.
let과 const의 차이점은 변수의 immutable여부이다.let은 변수에 재할당이 가능하지만 const는 변수 재선언, 재할당 모두 불가능하다개발시 반드시 협업을 하게 되는데 이 때 절대 변경하면 안되는 변수를 누군가가 건드렸을 때 let은 재할당이 가능해서 값이 변경되고 시스템에 문제가 생길 수 있지만 const로 선언하여 값을 할당했을 경우 그 값은 변경할 수 없도록 설정 되어 있어서 시스템문제로 이어지지 않아 코드 오류로 버그를 사전에 예방 할 수 있다.
선언 단계(Declaration phase)
변수를 실행 컨텍스트의 변수 객체에 등록
이 변수 객체는 스코프가 참조하는 대상이 된다
초기화 단계(Initialization phase)
변수 객체에 등록된 변수를 위한 공간을 메모리에 확보
이 단계에서 변수는 undefined로 초기화됨
할당 단계(Assignment phase)
undefined로 초기화된 변수에 실제 값을 할당
console.log(muscleUp); // 선언, 초기화상태
muscleUp = 'eat protein!'; // 선언, 초기화, 할당된 상태
var muscleUp;
console.log(muscleUp); //eat protein! 출력됨
// 중간의 var를 let이나 const로 하면 에러가 난다.muscleUp1();
muscleUp2();
function muscleUp1() {
console.log('eat protein!');
}
var foo2 = function() {
console.log('move!');
}
// muscleUp1은 함수형태여서 호이스팅이 일어나지만
// muscleUp2는 함수형태가 아닌데 두번째 줄에서 함수 선언하듯이 선언했으니 'move!'는 출력되지 않는다.스코프란?
변수의 유효범위를 뜻하며 현재 실행되는 Context를 말한다.
Context는 값과 표현식이 표현되거나 참조 될 수 있음을 의미한다.
변수 또는 다른 표현식이 해당 스코프 내에 없으면 사용할 수 없다.
스코프는 계층적인 구조를 갖고 있기 때문에 하위 스코프에 접근 가능하지만 반대는 불가하다.
클로저란?
외부함수보다 내부함수가 더 오래 유지되는 경우 외부함수 밖에서 내부함수가 호출되더라도 외부함수의 지역변수에 접근 할 수 있는 함수를 클로저라고 한다.
자신이 생성되었을 때ㅔ의 환경을 기억하는 함수이다.
클로저는 함수와 그 함수가 선언 되었을 때의 렉시컬 환경과의 조합이다.
lexical scope 예시
var scope = "I am global";
function whatismyscope(){
var scope = "I am just a local";
function func() {return scope;}
return func;
}
whatismyscope()() // I am just a local
// func 함수는, whatismyscope 함수의 범위 아래에서 정의된 것을 접근할수있기 때문
원래 함수 표현식에서 간단하게 표현 할수 있는 방법이다.
function을 빼고 ⇒ 넣어서 줄여 쓸 수 있다.
예시
// 일반 함수
var muscleUp = function () { console.log("muscleUp") }; // muscleUp
// 화살표 함수
var muscleUp = () => console.log("muscleUp"); // muscleUp
let arr1 = [1,2,3];
let arr2 = [4,5,6];
let arr = [...arr1, ...arr2];
console.log(arr); // [ 1, 2, 3, 4, 5, 6 ]
let arr1 = [1,2,3];
let arr2 = [4,5,6];
arr1.push(...arr2)
console.log(arr1); // [1,2,3,4,5,6]
let arr1 = [1,2];
let arr2 = [0, ...arr1, 3, 4];
console.log(arr2); // [0, 1, 2, 3, 4]let arr1 = ['스쿼트','바벨로우'];
let arr2 = [...arr1];
arr2.push('런지'); // arr2에 런지 요소추가
console.log(arr2); // [ '스쿼트','바벨로우', '런지' ]
// => 원본 배열 변경x
console.log(arr1); // [ '스쿼트','바벨로우' ]function add(...rest) {
let sum = 0;
for (let item of rest) {
sum += item;
}
return sum;
}
console.log( add(1) ); // 1
console.log( add(1, 2) ); // 3
console.log( add(1, 2, 3) ); // 6let input = [{name:'헬짱맨',age:12}, {name:'근육몬',age:12}, {name:'헬린이',age:2}];
//가장 어린 나이 구하기.
let minAge = Math.min( ...input.map((item) => item.age) );
console.log(minAge); // 2let currentState = { name: '철수', species: 'human'};
currentState = { ...currentState, age: 10};
console.log(currentState)// {name: "철수", species: "human", age: 10}
currentState = { ...currentState, name: '영희', age: 11};
console.log(currentState); // {name: "영희", species: "human", age: 11}구조분해할당이란 배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 표현식이다.
let 근성장 = ["8시간", "근력운동", "단백질"];
let [수면, 운동, 영양소] = 근성장;
console.log(수면); // "8시간"
console.log(운동); // "근력운동"
console.log(단백질); // "영양소"
["8시간", "근력운동", "단백질"] = [수면, 운동, 영양소]
// => 위의 식도 같은 콘솔값 출력됨let o = {p: 42, q: true};
let {p, q} = o;
console.log(p); // 42
console.log(q); // true이번 과제를 통해 내가 무엇을 정확히 알고 있는지 모르고 있는지 확실히 알게 되어 너무 좋았다.
개념을 설명하라고 하니 여기저기 mdn과 다른 블로그의 정리된 글을 참조하기 바빴다. 앞으로 자주 사용하도록 해서 나의 지식으로 만드는 과정이 필요할듯 하다.
가끔 오류발생시 어디서 값이 재할당 되었는지 참조했는지 찾는 과정에서 우왕좌왕 했었는데 글을 정리하면서 그 부분은 좀 해소 된 듯 하다.
아직 많이 모르겠지만 앞으로 더 직접 해보면서 화이팅해보자
참조
https://hanamon.kr/javascript-호이스팅이란-hoisting/
https://velog.io/@whow1101/MDN-번역-Scope