[Javascript] 자바스크립트 핵심 한 눈에 보기!_(JavaScript Koans)

wool·2022년 7월 13일

Javascript

목록 보기
4/10

intro


자바스크립트 문법을 이제 막 배웠고 오늘은 걸음마를 떼기 위한 시작점으로

개념을 정리 할 수 있도록 10개의 문제를 풀도록 했다.

해결해야 할 자바스크립트 파일의 수는 10개지만 한 파일에 몇가지 문제가 모여있고

총 통과해야할 테스트는 50가지였다.

페어분과 함께 논의하는 과정을 통해 빠른 시간 안에 모든 테스트를 통과 할 수 있었다.

간단한 문제처럼 보였지만 헷갈리는 부분도 있었고 이해 가지 않는 답이 나올 때는 페어님과

머리를 맞대고 도대체 왜 답이 이렇게 출력되는지에 대해 확실히 머릿속에 새길 수 있도록 서로 설명하고 이해하면서 문제를 풀어나갔다.

스스로 이해했다고 주장하며 정리하지만 머리속에서 증발 될 것이기 때문에

이번 과제를 통해 자바스크립트의 핵심 문법을 나의 언어로 정리해서

증발 될 때 마다 이 글을 참고하려고 한다 :)

expect 함수


자바스크립트에서 테스트 하는 값과 기대값을 비교하기 위해 사용하는 함수이다.

사용법

expect(테스트하는값).기대하는조건 // 기대하는조건'에 해당하는 함수를 matcher라고 함.
  • true,false 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함수가 기대하는 조건과 부합.
    // 동치연산자 사용 시 == 사용하지 않게 주의
  • equal matcher 값을 비교하여 같은지 여부 확인하는 방법 반드시 ==가 아닌 ===을 사용해야 한다. 사용법
    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, let, const)


var는 function-scoped이고, letconst는 block-scoped이다.

var(**function-scoped)**

  • 함수(function) 단위로 유효범위(scope)를 정하는 것을 function-scoped라고 한다.
  • 변수 재선언 불가능
  • 엔지니어님의 말씀에 의하면 var는 사용하지 않는 방향으로 가고 있기 때문에 그냥 사용하지 않고 보지 않는것을 추천하셨고 무엇인지만 아는 정도면 된다고 하셨다.
  • 그래서 var에 대한 설명은 여기서 마무리..^^

let, const(block-scoped)

  • block scope는 대괄호({})를 단위로 범위를 정한다.
  • let과 const의 차이점은 변수의 immutable여부이다.
  • let은 변수에 재할당이 가능하지만 const는 변수 재선언, 재할당 모두 불가능하다
💡 'const'가 추천되는 이유

개발시 반드시 협업을 하게 되는데 이 때 절대 변경하면 안되는 변수를 누군가가 건드렸을 때 let은 재할당이 가능해서 값이 변경되고 시스템에 문제가 생길 수 있지만 const로 선언하여 값을 할당했을 경우 그 값은 변경할 수 없도록 설정 되어 있어서 시스템문제로 이어지지 않아 코드 오류로 버그를 사전에 예방 할 수 있다.

호이스팅(hoisting)


  • 코드가 실행하기 전 변수선언, 함수선언이 해당 스코프의 최상단으로 끌어 올려진 것 같은 현상을 말한다.
  • 자바스크립트엔진은 코드를 실행하기 전 실행 컨텍스트를 위한 과정에서 모든 선언을 스코프에 등록하기 때문에 코드 실행 전 이미 변수선언, 함수선언이 저장 되어 있어 선언문보다 참조, 호출이 먼저 나와도 오류 없이 동작한다.
  • 실행 컨택스트는 실행 가능한 코드가 실행되기 위해 필요한 환경을 의미하며 실행되기 전 이러한 실행 컨텍스트 과정(코드를 구분하는 과정)을 거친다.
  • 이 호이스팅이라는 용어를 자바스크립트 실행 컨텍스트에 의한 위에 설명한 현상을 호이스팅이라고 부른다는 것으로 이해하면 되겠다. 그 현상이란 선언이 코드 실행 보다 먼저 메모리에 저장되는 과정으로 인한 현상을 말한다.
  • 자바스크립트의 모든 선언에는 호이스팅이 일어난다.

변수선언과 호이스팅

  • 변수은 3단계에 걸쳐 생성된다.
    1. 선언 단계(Declaration phase)

      변수를 실행 컨텍스트의 변수 객체에 등록

      이 변수 객체는 스코프가 참조하는 대상이 된다

    2. 초기화 단계(Initialization phase)

      변수 객체에 등록된 변수를 위한 공간을 메모리에 확보

      이 단계에서 변수는 undefined로 초기화됨

    3. 할당 단계(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!'는 출력되지 않는다.

스코프(Scope)


  • 스코프란?

    변수의 유효범위를 뜻하며 현재 실행되는 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

Array 다시 알아가기


  • type확인 배열은 type으로 값을 출력하면 객체로 분류된다. 배열인지 여부를 리턴하고자 할 땐 isArray()메서드를 사용해야한다.
  • 인덱스번호에 재할당 할 경우 그 자리에 없으면 새로운 인자가 생기고 인자가 이미 있는데 그 자리에 새로 할당 할 경우 새로 할당 한 값으로 배열에 변경이 생긴다.

스프레드 연산자


  • 스프레드 연산자란? 배열, 문자열, 객체 등 반복 가능한 객체를 개별 요소로 분리한다. 요소를 가져올 때에도 나머지 요소를 모두 가져올 때 사용한다.
  • 배열 병합시 스프레드 사용 예시
    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) ); // 6
    let input = [{name:'헬짱맨',age:12}, {name:'근육몬',age:12}, {name:'헬린이',age:2}];
    
    //가장 어린 나이 구하기.
    let minAge = Math.min( ...input.map((item) => item.age) );
    console.log(minAge); // 2
  • 객체에서의 스프레드연산자 예시
    let 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}

구조 분해 할당(Destructing Assignment)


구조분해할당이란 배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 표현식이다.

  • 구조분해할당 예시
    • 배열의 경우
      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

ending


이번 과제를 통해 내가 무엇을 정확히 알고 있는지 모르고 있는지 확실히 알게 되어 너무 좋았다.

개념을 설명하라고 하니 여기저기 mdn과 다른 블로그의 정리된 글을 참조하기 바빴다. 앞으로 자주 사용하도록 해서 나의 지식으로 만드는 과정이 필요할듯 하다.

가끔 오류발생시 어디서 값이 재할당 되었는지 참조했는지 찾는 과정에서 우왕좌왕 했었는데 글을 정리하면서 그 부분은 좀 해소 된 듯 하다.

아직 많이 모르겠지만 앞으로 더 직접 해보면서 화이팅해보자

참조

https://hanamon.kr/javascript-호이스팅이란-hoisting/

https://velog.io/@whow1101/MDN-번역-Scope

https://studyingpingu.tistory.com/48

https://paperblock.tistory.com/62

profile
허위 정보 발견 시 댓글로 남겨주시면 감사하겠습니다.

0개의 댓글