Number, String, Boolean, undefined, null, Symbol(ES6), Bigint
// ex
let x = 2;
let y = x; // x값을 복사하여 y에 저장 y = 2
y = 3; // x는 그대로 2. y값만 재할당 된 것. y = 3
Array, Object, Function
메모리 주소(참조값)는 Stack에 저장
Q. 왜 동적(dynamic)인 데이터 저장소를 사용하는가?
데이터 추가,삭제 과정에서 고정된 데이터 공간은 비효율적이므로
상황에 따라 동적으로 변하는 데이터 저장소가 적합하다
// ex
let x = { foo: 3 };
let y = x; // y에 x의 주소를 참조
y.foo = 2; // 같은 주소를 참조하므로, x값이 y값과 동일하게 변경됨
참조자료형 === 참조자료형
끼리의 주소값은 다르다고 판단한다===
(strict equality)는 주소값이 같은지 확인한다===
로 비교할시 false를 반환한다console.log([1,2,3] === [1,2,3]); // false
console.log({ foo: 'bar' } === { foo: 'bar' }); // false
console.log([] === []); // false
주소(참조)를 복사
중첩된 구조를 변경하면 원본과 복사본 모두 영향이 미친다
- 객체 안 객체가 있을 때,
내부에서 1개 객체라도 원본 객체를 참조한다면 얕은 복사다.
// ex)
const arr = [1, 2, [3, 4]];
const copied = arr.slice();
copied[2].push(5);
console.log(arr); // [1, 2, [3, 4, 5]]
console.log(copied); // [1, 2, [3, 4, 5]]
arr.slice()
//arr.slice()
const arr = [1, 2, [3, 4]];
const copied = arr.slice();
copied[2].push(5); //arr에도 push되어 있음 [1, 2, [3, 4, 5]]
Object.assign
//예 1 - 배열
const arr = [1, 2, [3, 4]];
const copied = Object.assign([], arr);
copied[2].push(5);
console.log(arr) //arr에도 push되어 있음
//예 2 - 객체
let origin = {
a: 1,
b: { c: 2 }
};
let copy = Object.assign({}, origin);
copy.b.c = 3
console.log(origin === copy) // false
console.log(origin.b.c === copy.b.c) // true
...spread
//예 1 - 배열
const arr = [1, 2, [3, 4]];
const copied = [ ...arr ];
copied[2].push(5);
console.log(arr) //arr에도 push되어 있음
//예 2 - 객체
const obj = {
a: 1,
b: {
c: 2,
}
}
const newObj = {...obj};
newObj.b.c = 99;
console.log(obj === newObj); // false
console.log(obj.b.c); // 99
console.log(obj.b.c === newObj.b.c); // true
새로운 주소에 실제 값만 복사
복사본과 원본의 주소는 공유안한다
new Date()
, 함수 역시 JSON.stringify가 처리할 수 없는 객체const arr = [1, 2, [3, 4]];
const copied = JSON.parse(JSON.stringify(arr));
copied[2].push(5);
console.log(arr); // [1, 2, [3, 4]]
console.log(copied); //[1, 2, [3, 4, 5]]
재귀함수를 이용
복잡하다
라이브러리(lodash, ramda 등) 사용
설치를 해야하며 낮은 퍼포먼스를 가진다
// 'npm install lodash'로 설치 후, Node.js 환경에서 실행
const _ = require('lodash');
let obj1 = { name: 'hi', age: 22 };
let obj3 = _.cloneDeep(obj1);
obj3.name = 'hello';
console.log(obj1); // { name: 'hi', age: 22 }
console.log(obj3); // { name: 'hello', age: 22 }
heap
stack call stack
event loop
callback queue
web apis
노마드코더 - (EP 03.) 자바스크립트 개발자라면 알아야하는 핵심 컨셉 33개 | #3. Value Types and Reference Types
어쨌든 이벤트 루프는 무엇입니까? | Philip Roberts | JSConf EU
그림출처 - How JavaScript works: an overview of the engine, the runtime, and the call stack