const sKey = Symbol("Hello!");
const user = {
key: "일반 정보!",
[sKey]: "민감한 정보!",
};
console.log(user.key); // 일반 정보!
console.log(user["key"]); // 일반 정보!
console.log(user[sKey]); // 민감한 정보!
console.log(user[Symbol("Hello!")]); // undefined
console.log(sKey); // Symbol(Hello!)
console.log(typeof sKey); // symbol
keys.js
export const birthKey = Symbol("Date of birth!");
export const emailsKey = Symbol("Emails!");
hs.js
import { birthKey, emailsKey } from "./keys";
export default {
firstName: "HyunSung",
lastName: "Lim",
age: 20,
[birthKey]: new Date(2004, 9, 10, 17, 30),
[emailsKey]: ["asd@naver.com", "qwe@gmail.com"],
};
main.js
import hs from "./hs";
import { birthKey, emailsKey } from "./keys";
// 일반적으로 Symbol로 만든 key는 콘솔로 조회할 수 없습니다.
console.log(hs);
console.log(Object.keys(hs));
for (const key in hs) {
console.log(hs[key]);
}
// 하지만 Symbol데이터를 할당하는 코드가 있는 파일을 직접 가져오면 조회가 가능합니다.
console.log(hs[birthKey]);
console.log(hs[emailsKey]);
BigInt
는 길이 제한이 없는 정수(integer)입니다.2^53 -1
)보다 큰 정수를 표현할 수 있습니다.n
을 붙이거나 BigInt()
를 호출해 생성합니다.console.log(1234567890123456789012345678901234567890);
console.log(1234567890123456789012345678901234567890n);
console.log(BigInt(1234567890123456789012345678901234567890));
const a = 11n;
const b = 22;
// 숫자 => BigInt
console.log(a + BigInt(b)); // 33n
console.log(typeof (a + BigInt(b))); // bigint
// BigInt => 숫자
console.log(Number(a) + b); // 33
console.log(typeof (Number(a) + b)); // number
let a = 1;
let b = a;
b = 2;
console.log(b); // 2
console.log(a); // 1
let a = { x: 1 };
let b = a;
b.x = 2;
console.log(b); // {x: 2}
console.log(a); // {x: 2}
a.x = 7;
console.log(b); // {x: 7}
console.log(a); // {x: 7}
b.x = 1;
console.log(b); // {x: 1}
console.log(a); // {x: 1}
// 일치 연산자는 엄밀히 말해 메모리 주소가 같은 지를 비교합니다.
console.log(a === b); // true
let a = { x: 1 };
let b = { x: 1 };
// 참조형 데이터는 같은 모양이더라도 다른 메모리 주소를 할당받습니다.
console.log(a === b); // false
b.x = 2;
console.log(b); // {x: 2}
console.log(a); // {x: 1}
let a = [1, 2, 3];
let b = a;
b[0] = 4;
console.log(b); // [4, 2, 3]
console.log(a); // [4, 2, 3]
객체 얕은 복사
const a = { x: 1 };
// const b = Object.assign({}, a);
const b = { ...a };
b.x = 2;
console.log(b); // {x: 2}
console.log(a); // {x: 1}
객체 깊은 복사
- lodash
설치
const a = { x: { y: 1 } };
const b = { ...a }; // 얕은 복사!
b.x.y = 2;
console.log(b); // {x: {y: 2}}
console.log(a); // {x: {y: 2}}
import cloneDeep from "lodash/cloneDeep";
const a = { x: { y: 1 } };
const b = cloneDeep(a); // 깊은 복사!
b.x.y = 2;
console.log(b); // {x: {y: 2}}
console.log(a); // {x: {y: 1}}
배열 얕은 복사
const a = [1, 2, 3];
// const b = a.concat([]);
const b = [...a];
b[0] = 4;
console.log(b); // [4, 2, 3]
console.log(a); // [1, 2, 3]
배열 깊은 복사
const a = [[1, 2], [3]];
const b = [...a];
b[0][0] = 4;
console.log(b); // [[4, 2], 3]
console.log(a); // [[4, 2], 3]
import cloneDeep from "lodash/cloneDeep";
const a = [[1, 2], [3]];
const b = cloneDeep(a);
b[0][0] = 4;
console.log(b); // [[4, 2], 3]
console.log(a); // [[1, 2], 3]
자바스크립트의 메모리 관리 방법으로 자바스크립트 엔진이 자동으로 데이터가 할당된 메모리에서 더 이상 사용되지 않는 데이터를 해제하는 것을 말합니다.
가비지 컬렉션은 개발자가 직접 강제 실행하거나 관리할 수 없습니다.
function createCount() {
let a = 0;
return function () {
return (a += 1);
};
}
const count = createCount();
console.log(count()); // 1
console.log(count()); // 2
console.log(count()); // 3
const count2 = createCount();
console.log(count2()); // 1
console.log(count2()); // 2
실제 사용시 유용한 예제
const h1El = document.querySelector("h1");
const h2El = document.querySelector("h2");
// 별도의 상태 관리가 필요!
let h1IsRed = false;
let h2IsRed = false;
h1El.addEventListener("click", () => {
h1IsRed = !h1IsRed;
h1El.style.color = h1IsRed ? "red" : "black";
});
h2El.addEventListener("click", () => {
h2IsRed = !h2IsRed;
h2El.style.color = h2IsRed ? "red" : "black";
});
const h1El = document.querySelector("h1");
const h2El = document.querySelector("h2");
const createToggleHandler = () => {
let isRed = false;
return (event) => {
isRed = !isRed;
event.target.style.color = isRed ? "red" : "black";
};
};
// h1, h2뿐만 아니라 요소를 점점 늘려갈 때도 재사용가능한 코드로 작성해줄 수 있습니다.
h1El.addEventListener("click", createToggleHandler());
h2El.addEventListener("click", createToggleHandler());
window.hello = "Hello world!";
window.hs = { name: "hs", age: 20 };
<body>
<button>Remove!</button>
<div class="parent">
<div class="child">1</div>
<div class="child">2</div>
</div>
</body>
const btn = document.querySelector("button");
const parent = document.querySelector(".parent");
// 버튼을 계속 눌러봐도 요소는 삭제되었지만, 콘솔을 확인해보면 데이터는 남아있습니다.
btn.addEventListener("click", () => {
console.log(parent);
parent.remove();
});
해결 방법
const btn = document.querySelector("button");
btn.addEventListener("click", () => {
const parent = document.querySelector(".parent");
console.log(parent); // 두 번째 클릭부터 null
parent && parent.remove();
});
let a = 0;
setInterval(() => {
a += 1;
}, 100);
setTimeout(() => {
console.log(a);
}, 1000);
해결 방법
let a = 0;
const intervalId = setInterval(() => {
a += 1;
}, 100);
setTimeout(() => {
console.log(a);
clearInterval(intervalId);
}, 1000);
const getFn = () => {
let a = 0;
return (name) => {
a += 1; // 메모리 누수 발생
console.log(a);
return `Hello ${name}~`;
};
};
const fn = getFn();
console.log(fn("HS")); // 1 HS
console.log(fn("Neo")); // 2 Neo
console.log(fn("Lewis")); // 3 Lewis
해결 방법
const getFn = () => {
let a = 0;
return (name) => {
return `Hello ${name}~`;
};
};
const fn = getFn();
console.log(fn("HS")); // HS
console.log(fn("Neo")); // Neo
console.log(fn("Lewis")); // Lewis