Section1

코드스테이츠 프론트엔드 부트캠프 15일차

Heemok 2023. 5. 1. 16:55

2023-05-01(월)

Unit 9 회고 및 Koans 복습

 

------------------------------------------------------------------------------------------------------------------------------------------------

 

Chapter1. 원시 자료형과 참조 자료형

  • 원시 자료형(primitive data type)과 참조 자료형(reference data type)의 구분이 왜 필요한지 이해할 수 있다.

= 원시 자료형의 경우 변수에 값을 할당하면 메모리 공간에 값 자체가 저장되며, 값을 다른 변수에 할당하면

원시 값 자체가 복사되어 전달된다. 원시 자료형은 변경 불가능한 값이고 읽기 전용인 값이다.

= 참조 자료형의 경우 변수에 값을 할당하면 메모리 공간에 주솟값이 저장되며, 다른 변수에 값을 할당하면 주솟값이 복사되어 전달된다. 참조 자료형은 변경이 가능한 값이다.

  • 원시 자료형과 참조 자료형의 차이를 이해하고, 각자 맞는 상황에서 사용할 수 있다.

= 원시 자료형의 경우 값 자체의 복사가 일어나기 때문에 원본과 복사본중 하나를 변경해도 다른 하나에 영향을 끼치지 않지만 참조 자료형의 경우 얕은복사를 했을 경우 다른 복사본에게도 영향이 간다.

  • 원시 자료형이 할당될 때는 변수에 값(value) 자체가 담기고, 참조 자료형이 할당될 때는 보관함의 주소(reference)가 담긴다는 개념을 코드로 설명할 수 있다.
  • 참조 자료형은 기존에 고정된 크기의 보관함이 아니라, 동적으로 크기가 변하는 특별한 보관함을 사용한다는 것을 이해할 수 있다.
  • 참조 자료형인 값을 복사하는 방법에 대해서 이해한다.

얕은 복사를 했을 경우 다른 복사본이나 원본의 값이 바뀐경우 다른 복사본이나 원본의 값도 같이 바뀌지만 

ex) slice(), Object.assign(), rest문법 등

깊은 복사를 했을경우 다른 복사본이나 원본의 값이 바뀌어도 다른 복사본이나 원본의 값은 바뀌지 않는다

하지만 객체에서 객체안에 다른 객체나 함수가 존재하는 경우에는 완전한 복사가 이루어지지 않는다.

ex) JSON.stringify()

Chapter2. 스코프

  • 스코프의 의미와 적용 범위를 이해한다.

= 스코프란 변수의 유효범위를 말한다. 

= 변수에 접근할 수 있는 범위가 존재하는데  중괄호 안쪽에 변수가 선언되어있는가, 바깥쪽에 선언되어있는가가 중요하다. 이 범위를 우리는 스코프라고 부른다.

  • 스코프의 주요 규칙을 이해한다.

= 1. 바깥쪽 스코프에서 선언한 변수는 안쪽 스코프에서 사용 가능합니다. 반면 안쪽에서 선언한 변수는 바깥쪽 스코프에서는 사용을 할 수 없습니다.

= 2. 스코프는 중첩이 가능하다는 것입니다.

= 3. 지역 변수는 전역 변수보다 더 높은 우선순위를 가진다.

 

  • 전역 스코프와 지역 스코프의 차이를 이해한다.

= 전역스코프는 바깥쪽 스코프를 말하고 전역이 아닌 다른 스코프는 모두 지역 스코프 라고 부릅니다

= 지역 스코프에서 생성된 변수는 지역변수, 전역 스코프에서 생선된 변수는 전역 변수입니다..

  • block scope와 function scope의 차이를 이해한다.

= 중괄호를 기준으로 범위가 구분되는 이를 블록 스코프라고 합니다.

= 함수로 둘러싼 범위를 함수 스코프라고 합니다.

  • 변수 선언 키워드(let, const, var)와 스코프와의 관계를 설명할 수 있다.

= var 키워드는 값의 재할당과 재선언이 가능하고 블록 스코프를 무시하지만 별로 사용하지 않는것을 추천합니다.

  • 전역 객체가 무엇인지 설명할 수 있다.

Chapter3. 클로저

  • 클로저 함수의 정의와 특징에 대해서 이해할 수 있다.

= 어휘적 환경을 기준으로 외부 함수의 변수에 접근할 수 있는 내부 함수를 말한다.

  • 클로저가 갖는 스코프 범위를 이해할 수 있다.
  • 클로저를 이용해 유용하게 쓰이는 몇 가지 패턴을 이해할 수 있다.

Chapter4. ES6 신규 문법

  • spread/rest 문법을 사용할 수 있다.
  • 구조 분해 할당을 사용할 수 있다.

------------------------------------------------------------------------------------------------------------------------------------------------

Koans 복습 문제

4-2 / 4-5 /8-5 /9-5 번 문제 복습

 

4-2번 문제

it('lexical scope에 대해서 확인합니다.', function () {
    let message = 'Outer';

    function getMessage() {
      return message;
    }

    function shadowGlobal() {
      let message = 'Inner';
      return message;
    }

    function shadowGlobal2(message) {
      return message;
    }

    function shadowParameter(message) {
      message = 'Do not use parameters like this!';
      return message;
    }

    expect(getMessage()).to.equal('Outer');
    expect(shadowGlobal()).to.equal('Inner');
    expect(shadowGlobal2('Parameter')).to.equal('Parameter');
    expect(shadowParameter('Parameter')).to.equal('Do not use parameters like this!');
    expect(message).to.equal('Outer');
  });

 

처음 문제를 풀 당시 4번째 함수문에서 let 키워드를 사용하지 않고 전역변수를 사용하여서 값이 리턴되었을때

전역변수의 값이 바뀌어야 한다 생각해서 마지막 message에서 Do not use parameters like this! 라는 값을 넣어줬지만

Outer로 되는게 이해가 되지 않았는데, 코드를 자세히보다보니 Parameter 라는 값을 넣어줬기 때문에 그런것이란걸 알게 되었습니다.

 

 

4-5번 문제

it('lexical scope와 closure에 대해 다시 확인합니다.', function () {
    let age = 27;
    let name = 'jin';
    let height = 179;

    function outerFn() {
      let age = 24;  //27
      name = 'jimin';
      let height = 178; //179

      function innerFn() {
        age = 26;  //26
        let name = 'suga';  // 'jimin'
        return height; 178
      }

      innerFn();

      expect(age).to.equal(26);
      expect(name).to.equal('jimin');

      return innerFn;
    }

    const innerFn = outerFn();

    expect(age).to.equal(27);
    expect(name).to.equal('jimin');
    expect(innerFn()).to.equal(178);
  });
});

복습하기

 

 

 

8-5번 문제

it('Object를 함수의 전달인자로 전달할 경우, reference가 전달됩니다.', function () {
    const obj = {
      mastermind: 'Joker',
      henchwoman: 'Harley',
      relations: ['Anarky', 'Duela Dent', 'Lucy'],
      twins: {
        'Jared Leto': 'Suicide Squad',
        'Joaquin Phoenix': 'Joker',
        'Heath Ledger': 'The Dark Knight',
        'Jack Nicholson': 'Tim Burton Batman',
      },
    };

    function passedByReference(refObj) {
      refObj.henchwoman = 'Adam West';
    }
    passedByReference(obj);
    expect(obj.henchwoman).to.equal('Adam West');

    const assignedObj = obj;
    assignedObj['relations'] = [1, 2, 3];
    expect(obj['relations']).to.deep.equal([1,2,3]);

    const copiedObj = Object.assign({}, obj);
    copiedObj.mastermind = 'James Wood';
    expect(obj.mastermind).to.equal('Joker');

    obj.henchwoman = 'Harley';
    expect(copiedObj.henchwoman).to.equal('Adam West');

    delete obj.twins['Jared Leto'];
    expect('Jared Leto' in copiedObj.twins).to.equal(false);

const copieObj 안에 Object.assign을 사용하여 얕은 복사를 하였는데, 여기서 obj.henchwoman 에 'Harley'로 값을 변동을 해주었는데 이상황에서는 제 생각에 맞게 한쪽만 변경이 되었는데 delete를 사용하여 obj.twins의 값을 변동해주었을 때는

두 객체 모두 변동이 생기는것이 의문이었는데 다시 공부를 진행하고 난후 얕은 복사를 할때 객체안에 객체가 존재한다면

그 객체는 값만 복사해오기 때문에 변동이 생기면 양쪽에서 둘다 변동이 되는것을 알게 되어 이해를 할 수 있었습니다.

 

 

9-5번 문제

it('Rest Parameter는 함수의 전달인자를 배열로 다룰 수 있게 합니다.', function () {
    // 자바스크립트는 (named parameter를 지원하지 않기 때문에) 함수 호출 시 전달인자의 순서가 중요합니다.
    function returnFirstArg(firstArg) {
      return firstArg;
    }
    expect(returnFirstArg('first', 'second', 'third')).to.equal('first');

    function returnSecondArg(firstArg, secondArg) {
      return secondArg;
    }
    expect(returnSecondArg('only give first arg')).to.equal(undefined);

    // rest parameter는 spread syntax를 통해 간단하게 구현됩니다.
    function getAllParamsByRestParameter(...args) {
      return args;
    }

    // arguments를 통해 '비슷하게' 함수의 전달인자들을 다룰 수 있습니다. (spread syntax 도입 이전)
    // arguments는 모든 함수의 실행 시 자동으로 생성되는 '객체'입니다.
    function getAllParamsByArgumentsObj() {
      return arguments;
    }

    const restParams = getAllParamsByRestParameter('first', 'second', 'third');
    const argumentsObj = getAllParamsByArgumentsObj('first', 'second', 'third');

    expect(restParams).to.deep.equal(['first','second','third']);
    expect(Object.keys(argumentsObj)).to.deep.equal(['0','1','2']);
    expect(Object.values(argumentsObj)).to.deep.equal(['first','second','third']);

    // arguments와 rest parameter를 통해 배열로 된 전달인자(args)의 차이를 확인하시기 바랍니다.
    expect(restParams === argumentsObj).to.deep.equal(false);
    expect(typeof restParams).to.deep.equal('object');
    expect(typeof argumentsObj).to.deep.equal('object');
    expect(Array.isArray(restParams)).to.deep.equal(true);
    expect(Array.isArray(argumentsObj)).to.deep.equal(false);

    const argsArr = Array.from(argumentsObj);
    expect(Array.isArray(argsArr)).to.deep.equal(true);
    expect(argsArr).to.deep.equal(['first','second','third']);
    expect(argsArr === restParams).to.deep.equal(false);
  });

argunments 외우기