과제 풀면서 헷갈렸거나 몰랐던 부분들 정리
매개변수로 num = 5
* 인자로 아무것도 없을 경우 num = 5가 적용되어 5를 반환
매개변수가 없을 경우 undefined가 아닌 디폴트 값을 사용하도록 설정할 수 있음
* 인자로 10을 넣을 경우 num에 5 대신 10이 적용되어 10을 반환
function defaultParameter(num = 5) {
// console.log(num)
// if(num === undefined) num = 5; 와 매개변수 num = 5 같은 코드
return num;
}
defaultParameter(10); // 10 콘솔로 확인한 num = 10
defaultParameter(); // 5 콘솔로 확인한 num = 5
화살표 함수의 클로저
const adder = x => {
return y => { // y 매개변수 1개
return x + y
}
}
console.log(adder(50)(10)) // 60
const subtractor = x => y => { // {return y => { return }} 바깥 {} 생략
return x - y
}
// const subtractor = x => y => x - y // 완전히 생략한 형태
console.log(adder(50)(10)) // 40
빈 배열, 빈 객체의 자료형과 length
* 빈 배열 : type은 object, length 0 (Array.isArray() 사용해야 배열인지 확인 가능)
* 빈 객체 : type은 object, length undefined
Object.keys(obj).length : object 요소의 개수를 구하는 법
또는 for...in으로 key를 순회할 때마다 count++로 구할 수 있음
const emptyArr = [];
console.log(typeof emptyArr === 'array'); // false
console.log(typeof emptyArr); // object
console.log(emptyArr.length); // 0
const emptyObject = {};
typeof emptyObject; // object
emptyObject.length; // undefined
emptyArr.length; // 0
arr.slice([begin[, end]]) 메서드
* 깊은 복사 (원본과 다른 주소를 갖는 배열을 반환)
* begin >= end 인 경우 빈 배열을 반환
* end >= arr.length 인 경우 begin부터 배열의 마지막까지 포함하는 배열을 반환
// slice
const arr = ['cat', 'dog', 'and', 'hamster'];
arr.slice(2, 2); // []
arr.slice(5, 1); // []
arr.slice(2, 20); // ['and', 'hamster'] begin부터 배열의 끝까지
원본 배열에서 요소의 얕은 복사본을 반환
객체 참조(및 실제 객체가 아님)의 경우, slice()는 객체 참조를 새 배열로 복사합니다.
원본 배열과 새 배열은 모두 동일한 객체를 참조합니다.
참조 된 객체가 변경되면 변경 내용은 새 배열과 원래 배열 모두에서 볼 수 있습니다.
* .repeat(num) : num 횟수만큼 앞의 문자를 반복함
ex) "abc".repeat(3); // "abcabcabc"
Object.assign() 메서드
* 원시형 타입은 값 자체가 복사 되지만 1depth는 깊은 복사, 2depth 이상은 얕은 복사
→ 깊은 복사만 할 수 있는 방식으로 통일해서 사용해야 함! (JSON, 라이브러리)
다차원 객체, 배열은 깊은 복사가 안 되기 때문에
다차원 속성들은 얕은 복사 (원본, 복사본의 변화가 서로 영향을 끼침)
ex) obj.twins 는 얕은 복사가 되어 delete obj.twins['Jared Leto'] 영향을 받아 copiedObj에서도 삭제됨
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',
},
};
const copiedObj = Object.assign({}, obj);
copiedObj.mastermind = 'James Wood';
delete obj.twins['Jared Leto'];
expect('Jared Leto' in copiedObj.twins).to.equal(false);
* 'property' in Object : true / false 반환
Object.assign()은 속성의 값을 복사하기 때문에, 깊은 복사를 수행하려면 다른 방법을 사용
만약 출처 값이 객체에 대한 참조라면 참조 값만 복사
spread 문법
const arr1 = [0, 1, 2];
const arr2 = [3, 4, 5];
const concatenated = [...arr1, ...arr2]; // [...arr1, ...arr2, ...arr2] 여러 개 사용 가능
expect(concatenated).to.deep.equal([0, 1, 2, 3, 4, 5]);
const merged = { ...fullPre, ...me }; // 두 객체의 속성(키)가 같다면 나중의 속성이 할당하는 값으로 바뀜
* 매개변수가 1개인 함수에 여러 인자를 넣으면 첫번째 인자만 함수에 전달되고 오류 발생하지 않음
* 매개변수가 2개인 함수에 하나의 인자를 넣으면 두번째 매개변수는 undefined
arguments 객체
arguments 객체는 함수에 전달된 인수에 해당하는 Array 형태의 객체
참고: "Array 형태"란 arguments가 length 속성과 더불어 0부터 인덱스 된 다른 속성을 가지고 있지만,
Array의 forEach, map과 같은 내장 메서드를 가지고 있지 않다는 뜻 (출처 MDN)
// arguments를 통해 '비슷하게' 함수의 전달인자들을 다룰 수 있음 (spread syntax 도입 이전)
// arguments는 모든 함수의 실행 시 자동으로 생성되는 '객체'
function getAllParamsByRestParameter(...args) { // 여러 인자가 들어왔을 때 풀어주지 않고
return args; // rest문법에 따라 하나의 배열로 리턴
} // ...args에 배열을 넣으면 [...args], 즉 배열 안의 배열이고 길이는 1
// let arr = [1, 2, 3, 4];
// gA(...arr); // 배열을 풀어서 배열에 넣음 [1, 2, 3, 4]
function getAllParamsByArgumentsObj() {
return arguments;
}
// ['first', 'second', 'third']
const restParams = getAllParamsByRestParameter('first', 'second', 'third');
//{'0': 'first, '1': 'second', '2': 'third'}
const argumentsObj = getAllParamsByArgumentsObj('first', 'second', 'third');
console.log(restParams); // ['first', 'second', 'third']
console.log(Object.keys(argumentsObj); // ['0', '1', '2']);
console.log(Object.values(argumentsObj); // ['first', 'second', 'third']
// arguments와 rest parameter를 통해 배열로 된 전달인자(args)의 차이를 확인하시기 바랍니다.
console.log(restParams === argumentsObj); // false
console.log(typeof restParams); // 'object'
console.log(typeof argumentsObj); // 'object'
console.log(Array.isArray(restParams); // true
console.log(Array.isArray(argumentsObj); // false
restParams.0 // error
restParams['0'] // 'first'
Array.from()
Array.from() 정적 메서드는 순회 가능 또는 유사 배열 객체에서
얕게 복사된 새로운 Array 인스턴스를 생성 및 반환 (출처 MDN)
객체 → 배열 (key 제외하고 value만 요소로 들어옴)
console.log(Array.from('foo'));
// Expected output: Array ["f", "o", "o"]
console.log(Array.from([1, 2, 3], (x) => x + x));
// Expected output: Array [2, 4, 6]
const argsArr = Array.from(argumentsObj); // 새로운 배열을 생성
console.log(Array.isArray(argsArr); // true;
console.log(argsArr); // ['first', 'second', 'third']
console.log(argsArr === restParams) // false
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/from
Array.from() - JavaScript | MDN
Array.from() 정적 메서드는 순회 가능 또는 유사 배열 객체에서 얕게 복사된 새로운 Array 인스턴스를 생성합니다.
developer.mozilla.org
rest 문법에서 인자가 부족할 경우
고정값은 undefined, 나머지는 [] 빈 배열
* 인자가 많은 경우 [1, 2, [3, 4, 5]] 형식으로 들어오게 됨 ( ...args = [3, 4, 5])
function getAllParams(required1, required2, ...args) {
return [required1, required2, args];
}
expect(getAllParams(123)).to.deep.equal([123, undefined, []]);
구조 분해
구조 분해 destructuring
배열의 첫번째 요소를 first, 두번째 요소를 second
const array = ['java', 'spring', 'im', 'course']
const [first, second] = array
console.log(first); // 'java'
console.log(second); // 'spring'
const [0, 1] = array;
console.log(0);
console.log(1);
// Uncaught SyntaxError: Invalid destructuring assignment target
const ['0', '1'] = array;
// Uncaught SyntaxError: Invalid destructuring assignment target
// rest/spread 문법을 배열 분해에 적용
const [f, s] = array;
console.log(f); // java
const array = ['java', 'spring', 'im', 'course']
const [start, ...rest] = array
expect(start).to.eql('java')
expect(rest).to.eql(['spring', 'im', 'course']) // rest 나머지 요소를 갖는 배열
객체의 분해
// rest/spread 문법을 객체 분해에 적용할 수 있습니다 #1
const student = { name: '최초보', major: '물리학과' }
const { name, ...args } = student // 객체 분해 cf.배열 -> 배열로
expect(name).to.eql('최초보')
expect(args).to.eql({major: '물리학과'}) // 객체 분해는 객체로