Koans는 불교에서 유래된 단어로, 결론을 내리기 전에 이게 왜 맞는지 깊게 고민한다는 의미를 가지고 있다고 한다. 답이 미리 제시되어 있기 때문에 고민 없이 풀면, 큰 어려움 없이 전부 다 풀 수 있지만 그게 왜 정답인지 깊게 고민해 보는 시간을 갖지 않는다면 충분히 성장하기 어려울 것이다. 즉, '왜?' 라는 물음에 대해 꼭 깊은 고찰을 하고 넘어가자는 의미이다.
describe('Object에 대해서 학습합니다.', function () {
it('Object의 기본을 확인합니다.', function () {
const emptyObj = {};
expect(typeof emptyObj === 'object').to.equal(true);
expect(emptyObj.length).to.equal(undefined); // Object의 length **
Object의 길이
- 배열의 길이를 구하듯이 a.length 를 쓰면 undefined가 뜬다.
- Object.keys(a).length 나 Object.values(a).length를 쓰면 된다.
(Object.keys(a).length는 a 객체의 key 값을 배열 속에 쫙~ 담아준다.)
const megalomaniac = {
mastermind: 'Joker',
henchwoman: 'Harley',
getMembers: function () {
return [this.mastermind, this.henchwoman];
},
relations: ['Anarky', 'Duela Dent', 'Lucy'],
twins: {
'Jared Leto': 'Suicide Squad',
'Joaquin Phoenix': 'Joker',
'Heath Ledger': 'The Dark Knight',
'Jack Nicholson': 'Tim Burton Batman',
},
};
expect(megalomaniac.length).to.equal(undefined);
expect(megalomaniac.mastermind).to.equal('Joker');
expect(megalomaniac.henchwoman).to.equal('Harley');
expect(megalomaniac.henchWoman).to.equal(undefined); // 대문자 W로 키값 일치 X
expect(megalomaniac.getMembers()).to.deep.equal(['Joker', 'Harley']); // this
expect(megalomaniac.relations[2]).to.equal('Lucy'); //
expect(megalomaniac.twins['Heath Ledger']).to.deep.equal('The Dark Knight');
});
this
method는 '어떤 객체의 속성으로 정의된 함수'를 말한다.
위의 megalomaniac 객체를 예로 든다면, getMembers는 megalomaniac 객체의 속성으로 정의된 함수인 '메소드'라고 할 수 있다. megalomaniac.getMembers()와 같은 형태로 사용(호출)할 수 있다.
사실은, 전역 변수에 선언한 함수도 웹페이지에서 window 객체의 속성으로 정의된 함수라고 할 수 있다.
window. 접두사 없이도 참조가 가능하기 때문에(window.foo()라고 사용해도 됨) 생략하고 쓰는 것뿐이다. 이렇듯, method는 항상 '어떤 객체'의 method이다.
따라서 호출될 때마다 어떠한 객체의 method일 텐데, 그 '어떠한 객체'를 묻는 것이 this이다.
예시로, obj이라는 객체 안에 foo라는 메서드를 선언하고, this를 반환한다고 했을 때 ( 예: let obj = {foo: function() {return this}}; )
obj.foo() === obj 이라는 코드에 true가 반환될 것이다.
심화되는 내용은 따로 포스팅 예정
deep.equal을 쓰는 경우
위의 사례에서만 추론했을 때 다음과 같다.
- 객체 속 함수의 값
- 객체 속 객체의 값 **** 궁금
* 객체 속 배열의 값은 .equal
it('Object의 속성(property)를 다루는 방법을 확인합니다.', function () {
const megalomaniac = { mastermind: 'Agent Smith', henchman: 'Agent Smith' };
expect('mastermind' in megalomaniac).to.equal(true); // 키 값이 있으면 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(false);
});
it("'this'는 method를 호출하는 시점에 결정됩니다.", function () {
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);
});
getFullYear()
콘솔로 찍어보고 느낀 점
** new Date(); 라고 써야만 현재 시각이 나온다.
(띄어쓰기, 대문자)
** new Date.getFullYear(); 은 생성자가 아니라고 한다. 일단은 참고자료 첨부 (미래의 내가 읽어줄거야)
** newDate라는 변수에 new Date();를 할당했다.
- .getFullYear() : 현재 년도 출력
- .getMonth() : 월을 출력 (0부터 시작하므로 3월이 2로 출력)
- .getDate() : 날짜를 출력
- .getDay() : 요일을 출력 (월요일 = 1)
it('객체의 method를 정의하는 방법을 확인합니다.', function () {
const megalomaniac = {
mastermind: 'Brain',
henchman: 'Pinky',
getFusion: function () {
return this.henchman + this.mastermind;
},
battleCry(numOfBrains) {
return `They are ${this.henchman} and the` + ` ${this.mastermind}`.repeat(numOfBrains); // 백틱 앞에 띄어쓰기 포함한 .repeat()
},
};
expect(megalomaniac.getFusion()).to.deep.equal('PinkyBrain');
expect(megalomaniac.battleCry(3)).to.deep.equal('They are Pinky and the Brain Brain Brain');
});
. repeat()
str.repeat(count);
'abc'.repeat(-1); // RangeError
'abc'.repeat(0); // ''
'abc'.repeat(1); // 'abc'
'abc'.repeat(2); // 'abcabc'
'abc'.repeat(3.5); // 'abcabcabc' (count will be converted to integer)
'abc'.repeat(1/0); // RangeError
({ toString: () => 'abc', repeat: String.prototype.repeat }).repeat(2);
// 'abcabc' (repeat() is a generic method)
repeat() 메서드는 문자열을 주어진 횟수만큼 반복해 붙인 새로운 문자열을 반환한다.
repeat() is a generic method (궁금)
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); // ** 얕은 복사
});
});
Object.asign()
Object.assign() 메서드는 출처 객체들의 모든 열거 가능한 자체 속성을 복사해 대상 객체에 붙여넣고, 그 후 대상 객체를 반환한다.
Object.asign()은 얕은 복사(shallow copy)를 한다.
속성의 값을 복사하기 때문에(출처 값이 객체에 대한 참조라면 참조 값만 복사) 깊은 복사를 하려면 다른 방법을 사용해야 한다.
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);
// Expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget === target);
// Expected output: true
아래는 깊은 복사(deep copy)를 하는 방법이다.
function test() {
'use strict';
let obj1 = { a: 0 , b: { c: 0}};
let obj2 = Object.assign({}, obj1);
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
obj1.a = 1;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
obj2.a = 2;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}}
obj2.b.c = 3;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}
console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}}
// 깊은 복사
obj1 = { a: 0 , b: { c: 0}};
let obj3 = JSON.parse(JSON.stringify(obj1));
obj1.a = 4;
obj1.b.c = 4;
console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}}
}
test();
얕은 복사와 깊은 복사와 관련된 참고자료들
https://scotch.io/bar-talk/copying-objects-in-javascript
https://medium.com/watcha/깊은-복사와-얕은-복사에-대한-심도있는-이야기-2f7d797e008a
'FE > JavaScript' 카테고리의 다른 글
[JS] test를 통한 구조 분해 할당 개념 익히기 _Koans (0) | 2023.03.06 |
---|---|
[JS] test를 통한 원시자료형/참조자료형 개념 익히기 _Koans (0) | 2023.03.06 |
[JS] this (0) | 2023.03.06 |
[JS] test를 통한 array 개념 익히기 _Koans (0) | 2023.03.06 |
[JS] test를 통한 화살표 함수 개념 익히기 _Koans (0) | 2023.03.05 |