JavaScript 공부 - JavaScript Koans

0

JavaScript

목록 보기
2/11
post-thumbnail

Koans : Koans는 불교에서 유래된 단어로, 결론을 내리기 전에 이게 왜 맞는지 깊게 고민한다는 의미를 가지고 있다. 답이 어느정도 제시되어 있기 때문에 고민 없이 풀면, 큰 어려움 없이 전부 다 풀 수 있지만, 그게 왜 정답인지 깊게 고민해 보는 시간을 가짐으로써 주니어 개발자의 길로 한걸음 더 다가갈 수 있게 된다.

이번에 코드스테이츠에서 준비한 JavaScript Koans는 이전 Unit에서 학습을 했던 Git 활용법을 복습하도록 유도하면서 JavaScript의 다양한 주요 개념들을 다시 복기시킬 수 있는 문제들을 준비하였다.

  1. JavaScript의 타입
  2. 변수 선언 키워드 let과 const
  3. 화살표 함수
  4. 스코프
  5. 배열
  6. 객체
  7. spread
  8. 구조분해할당

1번부터 5번까지는 큰 생각 없이 풀 수 있는 문제였기에 6번부터 간단하게 이야기를 해보려고 한다.

객체 관련 문제

○ this는 method를 호출하는 시점에 결정됩니다

	const currentYear = new Date().getFullYear();
    const megalomaniac = {
      mastermind: 'James Wood',
      henchman: 'Adam West',
      birthYear: 1970,
      calculateAge: function (currentYear) {
        return currentYear - this.birthYear;
      },
      changeBirthYear: function (newYear) {
        this.birthYear = newYear;
      },
    };

    expect(currentYear).to.equal(2023);
    expect(megalomaniac.calculateAge(currentYear)).to.equal(53);

    megalomaniac.birthYear = 2000;
    expect(megalomaniac.calculateAge(currentYear)).to.equal(23);

    megalomaniac.changeBirthYear(2010);
    expect(megalomaniac.calculateAge(currentYear)).to.equal(13);

처음 this가 호출된 부분은 currentYear 함수가 호출되면서 currentYear-this.birthYear 부분에서 this가 호출되었다. 이후 하단의 expect(megalomaniac.calculateAge(currentYear))은 함수 내부에서 2023-this.birthYear가 되는데, 여기서 this.birthYear는 megalomaniac 내부의 birthYear로 결정되게 되면서 53과 같은 결과가 나오게 되는 것이다. 이후에도 birthYear를 바꿈으로써 this.birthYear의 크기를 바꾸는 등 this는 활용폭이 넓게 사용될 수 있다.

○ Object를 함수의 전달인자로 전달할 경우, reference가 전달됩니다.

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

passedByReference 함수 호출로 인해 henchwoman은 Adam West로 변경되어 있다.
copiedObj에게 Object.assign을 통해 객체를 복사하여 할당하였을 경우, copiedObj의 mastermind를 변경하여도 원래 obj의 mastermind는 변경되지 않는다.
obj의 henchwoman을 변경하더라도 copiedObj의 경우 변경되지 않고 처음에 변경되었던 Adam West로 고정되어 있다.
하지만 마지막에서 obj 객체 내부의 또 다른 객체인 twins의 경우에는 원본 객체인 obj에서 삭제를 하면 복사 객체인 copiedObj에도 영향을 미치게 된다(내부의 내부속성까지 영향을 미치진 않는듯) 따라서 같이 삭제되게 된다..!

객체 부분에서는 실무에 진입하게 된다면 마지막 부분에서 약간의 헷갈림이 올 것으로 예상된다. 얕은 복사와 깊은 복사에 대해서 완벽하게 깨우치고 넘어갈 필요가 있다.

이후 Spread의 경우 ...을 통해 전개 문법에 대해서 학습하고, 배열 병합, 객체 병합 등을 쉽게 실행할 수 있다 정도로 알고 넘어가도 된다.

구조분해할당
○ 객체를 분해합니다

  const student = { name: '박해커', major: '물리학과' }

    const { name } = student
    expect(name).to.eql('박해커')

name을 따로 뽑아내서 변경이 가능하다.

    const student = { name: '최초보', major: '물리학과' }
    const { name, ...args } = student

    expect(name).to.eql('최초보')
    expect(args).to.eql({major:'물리학과'})

앞서 배운 spread를 활용해서도 변경이 가능하다!

    const user = {
      name: '김코딩',
      company: {
        name: 'Code States',
        department: 'Development',
        role: {
          name: 'Software Engineer'
        }
      },
      age: 35
    }

    const changedUser = {
      ...user,
      name: '박해커',
      age: 20
    }

    const overwriteChanges = {
      name: '박해커',
      age: 20,
      ...user
    }

    const changedDepartment = {
      ...user,
      company: {
        ...user.company,
        department: 'Marketing'
      }
    }

    expect(changedUser).to.eql({name:'박해커', company: {
      name: 'Code States',
      department: 'Development',
      role: {
        name: 'Software Engineer'
      }
    },
    age: 20})

    expect(overwriteChanges).to.eql({
      name: '김코딩',
      company: {
        name: 'Code States',
        department: 'Development',
        role: {
          name: 'Software Engineer'
        }
      },
      age: 35
    })

spread를 이용하여 이전 객체를 불러온 후, 다시 재 선언하여 name과 age를 변경할 수 있다! 다만 overwriteChanges를 보면 name과 age를 이미 새로 선언한 후 ...user를 통해 불러왔는데, 이렇게 되면 overwrite가 되면서 마지막 아래의 name은 그대로 김코딩, 35살이 되어있는 것을 확인할 수 있다. 이러한 점만 주의한다면 spread와 구조분해할당을 활용하여 한층 폭넓게 JavaScript를 활용할 수 있을 것이다

0개의 댓글