2021년 1월 7일 복기

Ji Taek Lim·2021년 1월 7일

오늘은 하지 못했던 코플릿들과 과제들을 정리하려고 한다.

중요한 개념들을 정리한다.

코언즈에 나오는 중요한 개념

    mdn에 따르면 클로저의 정의는 다음과 같습니다. 반드시 기억하시기 바랍니다.
      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

      A closure is the combination of a function and the lexical environment within which that function was declared. This environment consists of any local variables that were in-scope at the time the closure was created.

      클로저는 함수와 함수가 선언된 어휘적 환경의 조합을 말한다.
      이 환경은 클로저가 생성된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성된다.

    여기서의 키워드는 "함수가 선언""어휘적(lexical) 환경"입니다. 
    특이하게도 자바스크립트는 함수가 호출되는 환경와 별개로, 기존에 선언되어 있던 환경 - 어휘적 환경 - 을 기준으로 변수를 조회하려고 합니다.
    유어클레스 영상에서 언급되는 "외부함수의 변수에 접근할 수 있는 내부함수"를 클로져 함수로 부르는 이유도 그렇습니다.

    클로저는 내부(inner) 함수가 외부(outer) 함수의 지역 변수에 접근할 수 있습니다.
    이를 유념하시고 클로저의 유즈 케이스를 검색해 보시기 바랍니다. 아래 검색 키워드를 활용합니다.
      function factories
      namespacing private variables/functions


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

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

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

      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);
  });
});

  it('Object의 속성(property)를 다루는 방법을 확인합니다.', function () {
    const megalomaniac = { mastermind: 'Agent Smith', henchman: 'Agent Smith' };

    expect('mastermind' in megalomaniac).to.equal(true);/// 이거는 뭐지??

    megalomaniac.mastermind = 'Neo';
    expect(megalomaniac['mastermind']).to.equal('Neo');

    expect('secretary' in megalomaniac).to.equal(false);

    megalomaniac.secretary = 'Agent Smith';
    expect('secretary' in megalomaniac).to.equal(true);

    delete megalomaniac.henchman;
    expect('henchman' in megalomaniac).to.equal(undefined);
  });

이거는 무슨 개념이지?


  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'); 
    
    ->reference가 전달되어서 copiedObj는 카피본이다.

    obj.henchwoman = 'Harley';
    expect(copiedObj.henchwoman).to.equal('Adam West'); 
    
    ->왜냐하면 위에 passedByReference에서 obj를 변경해주었고.
    -> copied는 121번째 줄에서 다시 만들어 주었고 obj는 원본이고 copiedObj는 복사본인데 이게 다른거니까. 위에서 변한 copied의 값을 가져온다.

    delete obj.twins['Jared Leto'];
    expect('Jared Leto' in copiedObj.twins).to.equal(false);
    
    ->함수 실행 위치를 잘 봐야한다. copiedObj는 delete보다 먼저 실행되었다.
    ///읭???

    
    마지막 테스트 코드의 결과가 예상과는 달랐을 수도 있습니다.
    'Object.assign'을 통한 복사는 reference variable은 주소만 복사하기 때문입니다. 
    이와 관련하여 얕은 복사(shallow copy)와 깊은 복사(deep copy)에 대해서 학습하시기 바랍니다.
    가이드가 될 만한 학습자료를 첨부합니다.
      https://scotch.io/bar-talk/copying-objects-in-javascript
      https://medium.com/watcha/깊은-복사와-얕은-복사에-대한-심도있는-이야기-2f7d797e008a
    
  });
});

이거 가 중요하다...

https://scotch.io/bar-talk/copying-objects-in-javascript

The Naive Way of Copying Objects

function copy(mainObj) {
  let objCopy = {}; // objCopy will store a copy of the mainObj
  let key;

  for (key in mainObj) {
    objCopy[key] = mainObj[key]; // copies each property to the objCopy object
  }
  return objCopy;
}

const mainObj = {
  a: 2,
  b: 5,
  c: {
    x: 7,
    y: 4,
  },
}

console.log(copy(mainObj));

let obj = {
  a: 1,
  b: {
    c: 2,
  },
}
let newObj = Object.assign({}, obj);
console.log(newObj); // { a: 1, b: { c: 2} }

obj.a = 10;
console.log(obj); // { a: 10, b: { c: 2} }
obj는 바뀌었다.
console.log(newObj); // { a: 1, b: { c: 2} }
newObj는 안바뀌었다.

newObj.a = 20;
console.log(obj); // { a: 10, b: { c: 2} }
obj는 안바뀌었다.
console.log(newObj); // { a: 20, b: { c: 2} }
newObj는 바뀌었다.

newObj.b.c = 30;
console.log(obj); // { a: 10, b: { c: 30} }
obj가 왜 바뀌지?
console.log(newObj); // { a: 20, b: { c: 30} }
newObj는 바뀌었다.

// Note: newObj.b.c = 30; Read why..
let obj = {
  a: 1,
  b: 2,
};
let objCopy = Object.assign({}, obj);
console.log(objCopy);
// Result - { a: 1, b: 2 }
let obj = {
  a: 1,
  b: 2,
};
let objCopy = Object.assign({}, obj);

console.log(objCopy); // result - { a: 1, b: 2 }
objCopy.b = 89;
console.log(objCopy); // result - { a: 1, b: 89 }
console.log(obj); // result - { a: 1, b: 2 }
  it('여러 개의 객체를 병합할 수 있습니다.', function () {
    const fullPre = {
      cohort: 7,
      duration: 4,
      mentor: 'hongsik',
    };

    const me = {
      time: '0156',
      status: 'sleepy',
      todos: ['coplit', 'koans'],
    };

    const merged = { ...fullPre, ...me };
    변수 'merged'에 할당된 것은 'obj1''obj2'의 value일까요, reference일까요?
    만약 (value, 데이터)이 복사된 것이라면, shallow copy일까요, deep copy일까요?

    expect(merged).to.deep.equal({
      cohort: 7,
      duration: 4,
      mentor: 'hongsik',
      time: '0156',
      status: 'sleepy',
      todos: ['coplit', 'koans'],
    });
  });

변수 'merged'에 할당된 것은 'obj1'과 'obj2'의 value일까요, reference일까요?
만약 값(value, 데이터)이 복사된 것이라면, shallow copy일까요, deep copy일까요?

이거 어렵다.

    function getAllParamsByRestParameter(...args) {
      return args;
    }
    const restParams = getAllParamsByRestParameter('first', 'second', 'third'); 
    expect(restParams).to.deep.equal(['first','second','third']); ////// ...args 를 했으니까 이게 배열이 되는거야
    // 그러니까 restPrams는 ...args를 썼고 그걸 그대로 가져왔어 ...arg를 쓰니까. ['first','second','third']가 나왔어.
    expect(Array.isArray(restParams)).to.deep.equal(true);//이거는 배열이라는거지
    

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

    expect(Object.keys(argumentsObj)).to.deep.equal(['0','1','2']); /// 오 key가 string type으로 나오는구나
    expect(Object.values(argumentsObj)).to.deep.equal(['first','second','third']);
    /// arguments도 쓰니까 ['first','second','third'] 가 나왔어..
    // arguments와 rest parmeter를 통해 배열로 된 인자(args)의 차이를 확인하시기 바랍니다.
    expect(Array.isArray(argumentsObj)).to.deep.equal(false); 

이거는 객체라는건가?

    

    expect(restParams === argumentsObj).to.deep.equal(false);

    expect(typeof restParams).to.deep.equal('object'); // 이거는 배열인데 배열의 상위 개념이니까 객체이고
    expect(typeof argumentsObj).to.deep.equal('object'); // 이거는 그냥 객체 이고



    const argsArr = Array.from(argumentsObj);
    //이거는 뭐야?
    
       expect(restParams === argumentsObj).to.deep.equal(false);

    expect(typeof restParams).to.deep.equal('object'); // 이거는 배열인데 배열의 상위 개념이니까 객체이고
    expect(typeof argumentsObj).to.deep.equal('object'); // 이거는 그냥 객체 이고



    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); //다른 주소다.

요약:arguments가 배열로 만들어줌,

restParameter가 배열로 만들어줌.

Array.from()

Array.from() 메서드는 유사 배열 객체(array-like object)나반복 가능한 객체(iterable object)를 얕게 복사해새로운Array 객체를 만듭니다.

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/from

map이랑 filter 차이 위에건 filter 아랫건 map

Array.from과 화살표 함수 사용하기
// Using an arrow function as the map function to
// manipulate the elements
Array.from([1, 2, 3], x => x + x);
// [2, 4, 6]

// Generate a sequence of numbers
// Since the array is initialized with `undefined` on each position,
// the value of `v` below will be `undefined`
Array.from({length: 5}, (v, i) => i);
// [0, 1, 2, 3, 4]

  it('Rest Parameter는 인자의 수가 정해져 있지 않은 경우에도 유용하게 사용할 수 있습니다.', function () {
    function sum(...nums) {
      let sum = 0;
      for (let i = 0; i < nums.length; i++) {
        sum = sum + nums[i];
      }
      return sum;
    }
    expect(sum(1, 2, 3)).to.equal(6);
    expect(sum(1, 2, 3, 4)).to.equal(10);
  });
profile
임지택입니다.

0개의 댓글