내 방식대로 이해한 내용/새로 알게된 것은 초록색으로 필기!
let variable = 'variable';
let variableCopy = 'variableCopy'; //3번재 줄 실행 'variable'
variableCopy = variable;
variable = variableCopy; //변수 variable에 variableCopy 값을 할당
console.log(variable) // 'variable'
const puppy = ['pinky', 'choco', 'brownie'];
let colored = puppy; //['pinky', 'choco', 'brownie']
puppy.push('milk'); //
colored; // ['pinky', 'choco', 'brownie', 'milk']
puppy[1] = 'vanilla';
allowedToDrink[1] // 'vanilla'
참조자료형을 변수에 할당하면 변수는 주소값을 참조하여 원본 데이터에 접근하기 때문에 할당된 데이터의 요소를 변경하면 원본의 데이터도 변경됨
const person = {
son: {
age: 9,
},
};
const boy = person.son;
boy.age = 20;
expect(person.son === { age: 20 }).to.equal(false);
person.son의 값은 {age: 20}이 맞지만 비교연산자로 비교되는 객체와 같은 주소값을 가지는지는 알 수 없기 때문에 false를 반환한다
const emptyArr = [];
typeof emptyArr === 'array' //false
const multiTypeArr = [
0,
1,
'two',
function () {
return 3;
},
{ value1: 4, value2: 5 },
[6, 7],
];
multiTypeArr[3] // function () { return 3; }
multiTypeArr[3]() // 3 -- 리턴값이 나옴
인덱스로 요소를 조회했을때 해당 인덱스의 요소가 함수면 함수를 그대로 출력하고, 해당 인덱스의 함수를 실행하면 리턴값이 나온다
const arr = [];
arr[0] = 1;
arr[1] = 2;
arr.push(3);
arr; // [1, 2, 3]
const poppedValue = arr.pop(); // 3 --잘려나온 값 반환
arr; // [1, 2]
const arr = ['zero', 'one', 'two', 'three', 'four', 'five'];
const copiedArr = arr.slice();
copiedArr[3] = 'changed in copiedArr';
arr[3] // 'three'
const arr = ['peanut', 'butter', 'and', 'jelly'];
arr.slice(1) // ['butter', 'and', 'jelly']
arr.slice(0, 2) // ['peanut', 'butter']
arr.slice(2, 2) // []
arr.slice(2, 20) // ['and', 'jelly']);
arr.slice(3, 0) // []
const arr = [];
const emptyObj = {};
arr.length; // 0
emptyObj.length; // undefined;
빈 배열의 길이는 0 이지만, 빈 객체의 길이는 undefined 이다
빈 객체 뿐만이 아니라 객체의 경우 길이를 받고싶으면 키 혹은 값을 사용하여 길이를 조회할 수 있다ex) Object.keys(obj).length또한 속성값이 객체 안에 있는지 확인하고 싶으면'key' in obj를 사용하여 반환받는 참/거짓 값으로 알 수 있다
const megalomaniac = {
mastermind: 'Joker',
henchwoman: 'Harley',
getMembers: function () {
return [this.mastermind, this.henchwoman];
}
}
megalomaniac.getMembers() // ['Joker','Harley']
객체의 속성값이 함수인 경우
obj,key()를 사용하여 함수를 사용할 수 있고 값은 함수의 리턴값이 된다
const currentYear = new Date().getFullYear(); //현재를 기준으로 년도를 불러옴
const megalomaniac = {
mastermind: 'James Wood',
henchman: 'Adam West',
birthYear: 1970,
calculateAge: function (currentYear) {
return currentYear - this.birthYear;
},
};
megalomaniac.calculateAge(currentYear) //53
여기서 매서드 호출시, 매서드 내부에 쓰인 this는 해당 메서드를 호출한 객체
megalomaniac를 말하게 된다
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);
delete obj.twins['Jared Leto'];
obj.henchwoman = 'Adam West';
copiedObj.henchwoman // 'Harley'
'Jared Leto' in copiedObj.twins // false
Object.assign()을 사용하여 변수 copiedObj는 빈 객체에 obj의 값을 복사해서 넣어주었기 때문에 객체 자체는 원본의 주소를 공유하지 않는 새로운 객체라고 볼 수 있다
const obj = { a: 1, b: { c: 2, }, }; const copiedObj = Object.assign({}, obj); copiedObj.b.c = 3 --- obj === copiedObj // false obj.b.c === copiedObj.b.c // true하지만 객체 안의 요소의 값이 객체인 경우, 요소의 객체 자체의 주소값은 없어지지 않는 것처럼 보인다. 이를
얕은 복사라고 하는데, 따라서 객체 안에 객체가 있는 경우 예시의number의 요소는 원본과 주소를 공유한다고 생각할 수 있다
❔ 얕은 복사란 객체를 복사할 때 위의 예제처럼 원래값과 복사된 값이 같은 참조를 가리키고있는 것을 말한다. 객체안에 객체가 있을 경우 한개의 객체라도 원본 객체를 참조하고 있다면 이를 얕은 복사라고 한다.
[참조]https://www.digitalocean.com/community/tutorials/copying-objects-in-javascript
const spread = [1, 2, 3];
const arr = [0, ...spread, 4]; //[0, 1, 2, 3, 4]
const arr1 = [0, 1, 2];
const arr2 = [3, 4, 5];
const concatenated = [...arr1, ...arr2]; //[0, 1, 2, 3, 4, 5]
arr1.concat(arr2); //[0, 1, 2, 3, 4, 5]
spread는 한 배열 안에 두 번 사용할 수도 있으며 concat()과 같은 역할을 한다
const obj1 = {
like: 'sleep',
status: 'study',
};
const obj2 = {
time: '03:40',
todos: ['coplit', 'koans'],
};
const merged = { ...obj1, ...obj2 };
console.log(merged.like === obj1.like); //true
spread를 사용해 합친 두 객체의 요소는 같은 참조값을 공유하는 것을 확인할 수 있다
얕은복사 참조
function returnFirstArg(firstArg) {
return firstArg;
}
returnFirstArg('first', 'second', 'third') //'first', 'second', 'third'
function returnSecondArg(firstArg, secondArg) {
return secondArg;
}
returnSecondArg('only give first arg') //undefined
함수의 매개변수가 두 개일때 전달인자가 하나뿐이고 두번째 매개변수를 리턴하면 undefined를 출력한다
function getAllParamsByRestParameter(...args) {
return args;
}
function getAllParamsByArgumentsObj() {
return arguments;
}
const restParams = getAllParamsByRestParameter('first', 'second', 'third');
const argumentsObj = getAllParamsByArgumentsObj('first', 'second', 'third');
restParams === argumentsObj // false
typeof restParams // 'object'
typeof argumentsObj // 'object'
Array.isArray(restParams) // true
Array.isArray(argumentsObj) // false
두 변수는 형태는 같게 생겼지만 다른 값으로 취급된다 arguments 객체를 이용해 만든 argumentsObj의 경우 배열 형태를 하고 있는 객체이다
Object.keys(argumentsObj) // ['0', '1', '2']
Object.values(argumentsObj) // ['first', 'second', 'third']
arguments 객체는
Object.keys(),Object.values(argumentsObj)를 이용하여 키를 인덱스, 값을 배열 요소로 갖는 객체임을 확인할 수 있다
function getAllParams(required1, required2, ...args) {
return [required1, required2, args];
}
getAllParams(123) // [123, undefined, []
...args 는 배열의 형태로 매개변수를 받기 때문에 전달인자가 없을 경우 빈 배열
[]을 반환한다
const array = ['apple', 'mango', 'lemon', 'banana']
const [first, second] = array
console.log(first) //'apple'
console.log(second) //'mango'
const array = ['apple', 'mango', 'lemon', 'banana']
const [start, ...rest] = array
console.log(start) //'apple'
console.log(rest) // ['mango', 'lemon', 'banana']
spread/rest 문법을 사용하여 배열을 분해할때 ...rest로 분해된 요소가 배열로 리턴되는 것을 주의해야 한다
const name = '가나다'
const age = 20
const person = {
name,
age,
level: 'Junior',
}
person = {name: '가나다', age: 20, level: 'Junior'}
const dog = { name: '콩이', sound: '멍멍' }
const { name, ...args } = dog
console.log(name) // '콩이'
console.log(args) // {sound: '멍멍'}
const user = {
name: '김',
company: {
name: 'N Inc',
department: 'Design',
role: {
name: 'Web designer'
}
},
age: 28
}
//1번 --- 유저 내용을 앞에 미리 둠
const changedUser = {
...user,
name: '박',
age: 24
}
//2번 --- 유저 내용을 뒤에 들고 옴
const overwriteChanges = {
name: '박',
age: 25,
...user
}
//3번
const changedDepartment = {
...user,
company: {
...user.company,
department: 'Marketing'
}
}
출력결과
//1번
expect(changedUser).to.eql({
name: '박',
company: {
name: 'N Inc',
department: 'Design',
role: {
name: 'Web designer'
}
},
age: 24
})
//2번
expect(overwriteChanges).to.eql({
name: '김',
company: {
name: 'N Inc',
department: 'Design',
role: {
name: 'Web designer'
}
},
age: 28
})
//3번
expect(changedDepartment).to.eql({
name: '김',
company: {
name: 'N Inc',
department: ''Marketing'',
role: {
name: 'Web designer'
}
},
age: 28
})
순서에 따라 덮어 씌우는 값이 바뀌니까 잘 확인하기 !