Unit 10์์ ๊ณต๋ถํ JavaScript์ ํต์ฌ ๊ฐ๋
๊ณผ ์ฃผ์ ๋ฌธ๋ฒ์ ์ ์ดํดํ๋ ์ง ํ์ธํ ์ ์๋ ๊ณผ์ ๋ก, pair ์ฝ๋ฉ ๋ฐฉ์์ผ๋ก ๋ฌธ์ ํ์ด๋ฅผ ์งํํ๋ค.
์ฃผ์ ๋ JavaScript์ ํ์
, ๋ณ์ ์ ์ธ ํค์๋ let๊ณผ const, ํ์ดํ ํจ์, ์ค์ฝํ, ๋ฐฐ์ด, ๊ฐ์ฒด, spread, ๊ตฌ์กฐ๋ถํดํ ๋น ๋ฑ์ผ๋ก ๊ตฌ์ฑ๋์ด์๋ค.
JavaScipt Koans๋ฅผ ํ์ตํ๋ ๊ณผ์ ์ ์๋์ ๊ฐ๋ค.
1) ํ์ด์ ํจ๊ป ๋ฌธ์ ๋ฅผ ํผ๋ค.(1์ฐจ ํ์ด)
2) 1์ฐจ ํ์ด ํ, ์๋ก ํ์ผ์ ๋ค์ด๋ฐ์ ํผ์์ ๋ฌธ์ ๋ฅผ ๋ค์ ํ์ด๋ณธ๋ค.
3) ์๋กญ๊ฒ ์๊ฒ ๋ ๊ฐ๋
์ด๋ ํท๊ฐ๋ ธ๋ ๋ฌธ์ ๋ค ์์ฃผ๋ก ๋ธ๋ก๊ทธ์ ์ ๋ฆฌํ๋ค.
// expect์ ์ ๋ฌ์ธ์๋ก ๋ค์ด๊ฐ ํํ์์ ํ๊ฐ ๊ฒฐ๊ณผ
expect(1 + '1').to.equal('11'); // number(n) + string('i') = string('ni')
expect(123 - '1').to.equal(122); // number(n) - string(i) = number(n-i), string์ +๋ง ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ
expect(1 + true).to.equal(2); // number(n) + true = number(n+1), true = 1 & false = 0
expect('1' + true).to.equal('1true'); // string(1) + true = string('1true'), string๊ณผ ๋ง์
ํ๋ฉด ๋ฌด์กฐ๊ฑด string์ผ๋ก ์ถ๋ ฅ๋๋ค.
์์ ๊ฐ์ ์ฝ๋ฉ ๋ฐฉ์์ ์์ํ๊ธฐ ์ด๋ ต๊ธฐ ๋๋ฌธ์ ํผํด์ผ ํ๋ค..!
//์ฐธ์กฐ ์๋ฃํ
const ages = [22, 23, 27];
allowedToDrink = ages;
expect(allowedToDrink === ages).to.equal(true);
expect(allowedToDrink === [22, 23, 27]).to.equal(false); // 1
//arr === [] ๊ฐ ์๋๋ ์ด์ ์ ๊ฐ๋ค! ์ฝํ๋ฆฟ ํ ๋ ์์ฃผ ์ด๋ฌ๋๋ฐ..
const nums1 = [1, 2, 3];
const nums2 = [1, 2, 3];
expect(nums1 === nums2).to.equal(false); // 2
const person = { son: {age: 9 }, };
const boy = person.son;
boy.age = 20;
expect(person.son.age).to.equal(20);
expect(person.son === boy).to.equal(true);
expect(person.son === { age: 9 }).to.equal(false);
expect(person.son === { age: 20 }).to.equal(false); // 3
์ฐธ์กฐ ํ์ ์ ๋ณ์์๋ ๋ฐ์ดํฐ์ ๋ํ ์ฃผ์๋ง์ด ์ ์ฅ๋๊ธฐ ๋๋ฌธ์ ๋ณด์ด๋ ๊ฐ์ด ๊ฐ์๋(์ฃผ์ 1,2,3), ๊ฐ๋ค๊ณ ์ธ์ํ ์ ์๋ค.
it("'const'๋ก ์ ์ธ๋ ๊ฐ์ฒด์ ๊ฒฝ์ฐ, ์์ฑ์ ์ถ๊ฐํ๊ฑฐ๋ ์ญ์ ํ ์ ์์ต๋๋ค.", function () {
const obj = { x: 1 };
expect(obj.x).to.equal(1); // key์ธ x์ ๊ฐ = 1
delete obj.x; // key์ธ x ์ญ์
expect(obj.x).to.equal(undefined); // x๊ฐ ์์ผ๋ฏ๋ก undefined ์ถ๋ ฅ
});
const
๋ก ์ ์ธ๋ ๋ณ์๋let
๊ณผ ๋ค๋ฅด๊ฒ ์ฌํ ๋น์ด ๋ถ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ์๋์น ์์ ๊ฐ์ ๋ณ๊ฒฝ์ ๋ฐฉ์งํ๋ค. ๋ฐ๋ผ์, ์ผ๋ฐ์ ์ผ๋ก const
๋ฅผ ์ฌ์ฉํด ๋ณ์๋ฅผ ์ ์ธํ๊ณ , ์ฌํ ๋น์ด ํ์ํ ๊ฒฝ์ฐ์๋ง let
์ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ถ์ฅ๋๋ค.
it('ํจ์ ์ ์ธ์(declaration)๊ณผ ํจ์ ํํ์(expression)์ ์ฐจ์ด๋ฅผ ํ์ธํฉ๋๋ค.', function () {
let funcExpressed = 'to be a function';
expect(typeof funcDeclared).to.equal('function'); // ํจ์ ์ ์ธ์: function ํ์
expect(typeof funcExpressed).to.equal('string'); // ํจ์ ํํ์: string ํ์
function funcDeclared() { //ํจ์ ์ ์ธ์
return 'this is a function declaration';
}
funcExpressed = function () { //ํจ์ ํํ์
return 'this is a function expression';
};
// ์๋ฐ์คํฌ๋ฆฝํธ ํจ์ ํธ์ด์คํ
(hoisting)์ ๋ํด์ ๊ฒ์ํด ๋ด
๋๋ค.
const funcContainer = { func: funcExpressed }; //ํจ์ ํธ์ด์คํ
๋ถ๊ฐ
expect(funcContainer.func()).to.equal('this is a function expression');
funcContainer.func = funcDeclared; // ํจ์ ํธ์ด์คํ
๊ฐ๋ฅ
expect(funcContainer.func()).to.equal('this is a function declaration');
ํจ์ ์ ์ธ์๊ณผ ํจ์ ํํ์์ ์ฐจ์ด๋ ๊ฐ๊ฐ ๋ค๋ฅธ(function, string) ํ์ ์ผ๋ก ์ธ์ํ๋ค๋ ์ ๊ณผ, ํจ์ ํธ์ด์คํ ์ ๊ฐ๋ฅ ์ฌ๋ถ์ ์๋ค.
โ ์ค์ฝํ๋ '๋ณ์์ ๊ฐ์ ์ฐพ์ ๋ ํ์ธํ๋ ๊ณณ'์ด๋ค.
ํด๋ก์ ๋ ๋ด๋ถ ํจ์๊ฐ ์ธ๋ถ ํจ์์ ์ง์ญ ๋ณ์์ ์ ๊ทผํ ์ ์์ผ๋ฉฐ ์ ์ฆ ์ผ์ด์ค๋ก Function factory์ Namespacing(privacy)๊ฐ ์๋ค.
it('Object์ ๊ธฐ๋ณธ์ ํ์ธํฉ๋๋ค.', function () {
const emptyObj = {};
expect(typeof emptyObj === 'object').to.equal(true);
expect(emptyObj.length).to.equal(undefined); // ๊ฐ์ฒด์๋ length ์์ฑ์ด ์์ผ๋ฏ๋ก undefined
length
์์ฑ์ ๋ฐฐ์ด๊ณผ ๋ฌธ์์ด์๋ง ์๋ ์์ฑ์ผ๋ก, ๊ฐ์ฒด์๋ ์กด์ฌํ์ง ์๋๋ค. ๊ฐ์ฒด ์์ ๊ฐ์ด ์์ด๋ length
์์ฑ ์ฌ์ฉ์, undefined
๋ฅผ ์ถ๋ ฅํ๋ค.
๊ฐ์ฒด์ ๊ธธ์ด๋ฅผ ์ถ๋ ฅํ๊ธฐ ์ํด์๋ Object.keys๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค. ex)Object.keys(obj).length
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);
},
};
expect(megalomaniac.getFusion()).to.deep.equal('PinkyBrain');
expect(megalomaniac.battleCry(3)).to.deep.equal('They are Pinky and the Brain Brain Brain'); // .repeat(n) => . ์์ ๊ฐ์ n๋ฒ ๋ฐ๋ณต
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'); // obj์ jenchwoman ๊ฐ ๋ณ๊ฒฝ
const copiedObj = Object.assign({}, obj); // obj๊ฐ์ฒด๋ฅผ assign ํจ์์ ์ธ์๋ก ์ ๋ฌํ์ฌ copiedObj ๊ฐ์ฒด ์์ฑ
copiedObj.mastermind = 'James Wood'; // copiedObj์ mastermind ๊ฐ ๋ณ๊ฒฝ
expect(obj.mastermind).to.equal('Joker'); // obj์ mastermind๋ ๊ทธ๋๋ก
obj.henchwoman = 'Harley'; // obj์ hanchwoman ๊ฐ ๋ณ๊ฒฝ
expect(copiedObj.henchwoman).to.equal('Adam West'); // copiedObj์ henchwoman์ ๊ทธ๋๋ก
delete obj.twins['Jared Leto']; // obj์ key์ธ twins ๊ฐ์ฒด์ Jared Leto ํค ์ญ์
expect('Jared Leto' in copiedObj.twins).to.equal(false); // ๊ฐ์ฒด ์์ ๊ฐ์ฒด -> ์์ ๋ณต์ฌ์ด๋ฏ๋ก ๋ฐ์ดํฐ์ ์ํฅ์ ์ค
'Object.assign'์ ํตํ ๋ณต์ฌ๋ ๊น์ ๋ณต์ฌ(deep copy)๋ก, reference๋ง ๋ณต์ฌํ๊ธฐ ๋๋ฌธ์ ๋ณต์ฌํ ๊ฐ์ฒด ๋ด์์ ๊ฐ์ ๋ณ๊ฒฝ์ด ์์ ๊ฒฝ์ฐ ์๋ณธ ๊ฐ์ฒด์๋ ์ํฅ์ ๋ผ์น์ง ์๋๋ค.
๊ทธ๋ฌ๋ ๊ฐ์ฒด ์์ ๊ฐ์ฒด๊ฐ ์์ ๊ฒฝ์ฐ ํ๊ฐ์ ๊ฐ์ฒด๋ผ๋ ์๋ณธ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๊ณ ์๋ค๋ฉด ์์ ๋ณต์ฌ(shallow copy)๋ก, ๋ฐ์ดํฐ์ ์ํฅ์ ์ค๋ค. ๋ฐ๋ผ์,delete obj.twins['Jared Leto'];
๋ copieObj ๊ฐ์ฒด์ ์ํฅ์ ์ค๋ค.
์์ ๋ณต์ฌ, ๊น์ ๋ณต์ฌ?
๋งํฌํ ์คํธ
function returnFirstArg(firstArg) {
return firstArg;
}
expect(returnFirstArg('first', 'second','third')).to.equal('first', 'second', 'third');
function returnSecondArg(firstArg, secondArg) {
return secondArg;
}
expect(returnSecondArg('only give firstarg')).to.equal(undefined);
//๊ฐ์ ํ๋๋ง ์
๋ ฅํ์ผ๋ฏ๋ก ๊ฐ์ฅ ์ฒซ ๋ฒ์งธ ์ ๋ฌ์ธ์์ธ firstArg์ ๊ฐ์ด ํ ๋น๋์๋ค.
//๊ทธ๋ฌ๋ secondArg๋ฅผ return ํ์ผ๋ฏ๋ก undefinde ์ถ๋ ฅ
์๋ฐ์คํฌ๋ฆฝํธ๋ named parameter๋ฅผ ์ง์ํ์ง ์๊ธฐ ๋๋ฌธ์ ํจ์ ํธ์ถ ์ ์ ๋ฌ์ธ์์ ์์๊ฐ ์ค์ํ๋ค.
// 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']); // key๊ฐ์ด index ๊ฐ์ผ๋ก ์ถ๋ ฅ
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'); // ๋ฐฐ์ด์ typeof ์์ฑ ์ฌ์ฉ์, object๋ก ์ถ๋ ฅ
expect(typeof argumentsObj).to.deep.equal('object');
expect(Array.isArray(restParams)).to.deep.equal(true);
expect(Array.isArray(argumentsObj)).to.deep.equal(false);
// rest parameter๋ ์ ๋ฌ์ธ์์ ์ผ๋ถ์๋ง ์ ์ฉํ ์ ๋ ์๋ค.
// rest parameter๋ ํญ์ ๋ฐฐ์ด
function getAllParams(required1, required2, ...args) {
return [required1, required2, args];
}
expect(getAllParams(123)).to.deep.equal([123, undefined, []]);
it('rest/spread ๋ฌธ๋ฒ์ ๊ฐ์ฒด ๋ถํด์ ์ ์ฉํ ์ ์์ต๋๋ค #3', () => {
const user = {
name: '๊น์ฝ๋ฉ',
company: {
name: 'Code States',
department: 'Development',
role: {
name: 'Software Engineer'
}
},
age: 35
}
const changedUser = { // ๋งจ ์์ ...user๋ก ์๋ณธ ๋ถ๋ฌ์จ ํ, ๊ทธ ๋ค์์ ๋๋จธ์ง ํค์ ๊ฐ์ ๋ณ๊ฒฝ
...user,
name: '๋ฐํด์ปค',
age: 20
}
const overwriteChanges = { // ๋ณ์ ์ ์ธ ์ดํ, ๋งจ ๋ง์ง๋ง์ ...user๋ก ์๋ณธ์ ๋ถ๋ฌ์ด(๋ณ๊ฒฝx)
name: '๋ฐํด์ปค',
age: 20,
...user
}
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
}) //...user์ ์์น์ ๋ฐ๋ผ ๊ฐ์ฒด์ ๊ฐ์ด ๋ฌ๋ผ์ง๋ค.
})
** ๋ฐฐ์ด ์๋ต
Reference: ์ฝ๋์คํ ์ด์ธ