์ด๋ฒ ํฌ์คํ ์์๋ ํ๋กํผํฐ ์ดํธ๋ฆฌ๋ทฐํธ์ ๋ํด ์์๋ณธ๋ค.
์ด ํฌ์คํ ์ ์ด์น๋ชจ๋์ ์๋ฐ์คํฌ๋ฆฝํธ deep dive 16์ฅ์ ์ฐธ์กฐํ์ฌ ์์ฑํ์์ต๋๋ค.
๋ณธ๋ฌธ ์ค ํ๋ฆฐ ๋ด์ฉ์ด ์๋ค๋ฉด ๋๊ธ์ ํตํด ์๋ ค์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค. ๐
ํ๋กํผํฐ ์ดํธ๋ฆฌ๋ทฐํธ์ ๋ํด ์๊ธฐ ํ๊ธฐ ์ ์, ์ํํ ์ดํด๋ฅผ ์ํด ๋จผ์ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ด๋ถ ์ฌ๋กฏ๊ณผ ๋ด๋ถ ๋ฉ์๋์ ๋ํด ์ดํด๋ณด์.๐๐
๋ด๋ถ ์ฌ๋กฏ๊ณผ ๋ด๋ถ ๋ฉ์๋๋ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ๋ด๋ถ ๋์์ ์ค๋ช ํ๊ธฐ ์ํด ECMAScript์์ ์ ์ํ ์์ฌ ํ๋กํผํฐ(pseudo property)์ ์์ฌ ๋ฉ์๋(pseudo method)์ด๋ค.
์ฆ ECMAScript ์ฌ์์ ๋ฑ์ฅํ๋ [[...]]๋ก ๊ฐ์ผ ์ด๋ฆ๋ค์ด ๋ด๋ถ ์ฌ๋กฏ๊ณผ ๋ด๋ถ ๋ฉ์๋์ด๋ค.
์กฐ๊ธ ์ฝ๊ฒ ์ด์ผ๊ธฐ ํ๋ฉด ECMAScript ๋ฌธ์์์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ด๋ถ ๋์์ ์ค๋ช ์ ์ํด ์ ์ํด ๋์ ๊ฐ์ ๋ฉ์๋๋ผ๊ณ ์ดํดํ๋ฉด ๋ ๋ฏ ํ๋ค.
They are defined by this specification purely for expository purposes.
However, each object within an implementation of ECMAScript must behave as specified by the internal methods associated with it.
The exact manner in which this is accomplished is determined by the implementation.
ECMAScript ๋ฌธ์์์ ๋ฐ์ทํ ๋ด๋ถ ์ฌ๋กฏ ์ ์์ธ๋ฐ, ํด์ํด ๋ณด๋ฉด '๋ด๋ถ ์ฌ๋กฏ์ ์ค๋ช ์ ๋ชฉ์ ์ผ๋ก ์ ์๋์์ง๋ง ์ค์ ๋ก ๋ด๋ถ์์ ๊ด๋ จ ๋ฉ์๋์ ์ํด ๋ช ์๋ ๋๋ก ๋์ํ๋ค' ๋ผ๊ณ ์จ์๋ค.
๊ทธ๋ฌ๋๊น ์ค์ ๋ก๋ ์์ง๋ง ๋น์ทํ๊ฑด ์๋( ๐คทโโ๏ธ ?) ์กด์ฌ๋ผ๊ณ ์ดํดํ๋ฉด ๋ ๊ฒ ๊ฐ๋ค.
๋ด๋ถ ์ฌ๋กฏ๊ณผ ๋ด๋ถ ๋ฉ์๋๋ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ๋ด๋ถ ๋ก์ง์ด๋ฏ๋ก ์ง์ ์ ์ผ๋ก ์ ๊ทผํ๊ฑฐ๋ ํธ์ถํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ง ์๋๊ฒ์ด ์์น์ด๋, [[prototype]]๊ณผ ๊ฐ์ ์ผ๋ถ ๋ด๋ถ ์ฌ๋กฏ๊ณผ ๋ด๋ถ ๋ฉ์๋์ ํํ์ฌ ๊ฐ์ ์ ์ผ๋ก ์ ๊ทผํ ์ ์๋ ์๋จ์ ์ ๊ณตํ๋ค. (ex : object.__proto__)
์ด์ ์ฌ์ ์ง์์ ํ์ตํ์ผ๋, ๋ณธ๊ฒฉ์ ์ผ๋ก ํ๋กํผํฐ ์ดํธ๋ฆฌ๋ทฐํธ์ ๋ํด ์์๋ณด์!
๊ฐ์ฒด๊ฐ ๊ฐ๋ ํ๋กํผํฐ์ ์ข ๋ฅ๋ ๋ฐ์ดํฐ ํ๋กํผํฐ, ์ ๊ทผ์ ํ๋กํผํฐ๋ก ๋๊ฐ์ง๊ฐ ์๋ค.
ํ๋กํผํฐ ์ดํธ๋ฆฌ๋ทฐํธ๋ ์ด๋ฌํ ๊ฐ์ฒด ๋ด๋ถ์ ๊ฐ๊ฐ์ ํ๋กํผํฐ๋ค์ ๋ํด์ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ด ๊ด๋ฆฌํ๋ ์์ฑ๊ฐ์ด๋ค.
ํด๋น ํ๋กํผํฐ๊ฐ ๋ฐ์ดํฐ ํ๋กํผํฐ๋, ์ ๊ทผ์ ํ๋กํผํฐ๋์ ๋ฐ๋ผ ์ฐ๊ด๋ ๋ด๋ถ ์ฌ๋กฏ์ด ๋ฌ๋ผ์ง๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ๊ฐ์ฒด์ ๋ฐ์ดํฐ ํ๋กํผํฐ๊ฐ ์์ฑ๋ ๋ ์๋์ผ๋ก ํ๋กํผํฐ์ ์์ฑ๊ฐ๋ค์ ์ ์ํ๋ค.
๊ตฌ์ฒด์ ์ธ ๊ฐ์ผ๋ก๋ ๊ฐ์ฒด์ ํ๋กํผํฐ์ ๋ํด ๊ฐ์ ๊ฐฑ์ ๊ฐ๋ฅํ๋๋ก ํ ๊ฒ์ธ์ง([[writable]]), ์ด๊ฑฐ ๊ฐ๋ฅํ๋๋ก ํ ๊ฒ์ธ์ง([[enumarable]]), ์ฌ์ ์ ๊ฐ๋ฅํ๋๋ก ํ ๊ฒ์ธ์ง([[configurable]])๊ฐ ์๋ค.
๋ง๋ก ์ค๋ช
ํด ๋์ผ๋ ์ข ์ด๋ ค์ด๋ฐ, Object.getOwnPropertyDescriptor
๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ์ ์ ์ผ๋ก ํ์ธ ํด๋ณผ ์ ์๋ค. ์ฝ๋๋ฅผ ํตํด ์ดํด๋ณด์.
const person = {
name: "Lee",
};
console.log(Object.getOwnPropertyDescriptor(person, "name"));
// { value: 'Lee', writable: true, enumerable: true, configurable: true }
์ ์ฝ๋์ ์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด person ๊ฐ์ฒด์ name ํ๋กํผํฐ์ ๋ํ ๋ฐ์ดํฐ ํ๋กํผํฐ๋ฅผ ํ์ธํด ๋ณผ ์ ์๋ค. (์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ด ์๋์ ์ผ๋ก value, writable, enmuerable, configurable attribute๋ฅผ ์ ์ํ๋ค๋ ์ฌ์ค๋ ๊ฐ์ด ํ์ธ ํ ์ ์๋ค!)
๋ฐ์ดํฐ ํ๋กํผํฐ ์ดํธ๋ฆฌ๋ทฐํธ๊ฐ ๊ฐ๋ ๊ฐ๊ฐ์ ์์ฑ์ ๋ํด ์กฐ๊ธ ๋ ์์ธํ ์ดํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
Object.defineProperty
๋ผ๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋น ํ๋กํผํฐ์ ๋ํ ์์ฑ๊ฐ์ ์ง์ ์ ์ํ ์ ์๋ค. ๊ทธ๋ ๋ค๋ฉด ์ ๋ง ์์ ์ด๋ ์ญ์ ๊ฐ ์๋๊ฒ ๋ง๋ค ์ ์๋์ง ํ๋ฒ ์คํํด๋ณด์!
const test = {};
Object.defineProperty(test, "cannotEdit", {
value: "cannotEdit",
writable: false,
enumerable: true,
configurable: false,
});
console.log(test); // { cannotEdit: 'cannotEdit' }
test.cannotEdit = "try edit..."; // ๋ณ๊ฒฝ ์๋
console.log(test); // { cannotEdit: 'cannotEdit' }
delete test.cannotEdit; // ์ญ์ ์๋
console.log(test); // { cannotEdit: 'cannotEdit' }
์์ ๊ฐ์ด ์ค์ ๋ก writable์ false๋ก ์ ์ํ๋ฉด, cannnotEdit์ด๋ property์ value๋ฅผ ์์ ํด๋ ์์ ๋์ด์ง์ง ์๊ณ ๋ฌด์๋๋ค.
๋๋ฒ์งธ๋ก ์ดํด๋ณผ ์ ๊ทผ์ ํ๋กํผํฐ๋ ์ ๊ทผ์ ํจ์๋ก ๊ตฌ์ฑ๋ ํ๋กํผํฐ๋ก, ์์ฒด์ ์ผ๋ก๋ ๊ฐ์ ๊ฐ์ง ์์ผ๋ฉฐ ๋ฐ์ดํฐ ํ๋กํผํฐ์ ๊ฐ์ ์ฝ๊ฑฐ๋ ๋ณ๊ฒฝํ ๋ ์ฌ์ฉ๋๋ค.
๋ฐ์ดํฐ ํ๋กํผํฐ์ ๋ง์ฐฌ๊ฐ์ง๋ก, ์ ๊ทผ์ ํ๋กํผํฐ๋ ์ฐ๋ฆฌ๊ฐ ์ง์ ์ ์ํ ์ ์๋ค. ์ ๊ทผ์ ํ๋กํผํฐ์ set๊ณผ get์ ์ง์ ์ ์ํด์ ์ฌ์ฉํด๋ณด๋ฉฐ ์ดํดํด๋ณด์!
test = {
first: "java",
second: "script",
get firstPlusSecond() {
// get์ ์ง์ ์ ์
return `${this.first}${this.second}`;
},
set firstPlusSecond(name) {
// set์ ์ง์ ์ ์
[this.first, this.second] = name.split(" ");
},
};
descriptor = Object.getOwnPropertyDescriptor(test, "firstPlusSecond");
console.log("firstPlusSecond", descriptor);
/* firstPlusSecond {
get: [Function: get firstPlusSecond],
set: [Function: set firstPlusSecond],
enumerable: true,
configurable: true
} */
console.log(test.firstPlusSecond);
// [[get]]์ด ํธ์ถ๋์ด javascript๋ฅผ ๋ฐํํ๋ค.
test.firstPlusSecond = "Type script";
// [[set]]์ด ํธ์ถ๋์ด first์ second์ ๊ฐ์ ๋ณ๊ฒฝํ๋ค.
console.log(test.firstPlusSecond);
// [[get]]์ด ํธ์ถ๋์ด Typescript๋ฅผ ๋ฐํํ๋ค.
์ ๊ทผ์ ํ๋กํผํฐ get๊ณผ set์ ์ ์ํ์ฌ first์ second์ ์ง์ ์ ๊ทผํด ๋ณด๊ณ ๋ณ๊ฒฝํด๋ณด์๋ค.
์ด์ฒ๋ผ ๊ฐ์ฒด์ ์ ๊ทผ์ ํ๋กํผํฐ ํจ์์ธ get๊ณผ set์ ์ ์ํด ๋์ผ๋ฉด, ํด๋น ํ๋กํผํฐ์ ๊ฐ์ ๊ฐ์ ธ์ฌ๋๋ get
์ ํธ์ถํ๊ณ , ํด๋น ํ๋กํผํฐ์ ๊ฐ์ ์ ์ฅํ ๋๋ set
์ ํธ์ถ ํ๋ค!
๋ด๋ถ ์ฌ๋กฏ & ๋ด๋ถ ๋ฉ์๋๋ถํฐ ํ๋กํผํฐ ์ดํธ๋ฆฌ๋ทฐํธ๊น์ง ๋ด์ฉ์ด ์ข ๋ง์๋ค.
๋ง์ง๋ง์ผ๋ก ํ๋ฒ ์ ๋ฆฌํด๋ณด์.
- ๋ด๋ถ ์ฌ๋กฏ๊ณผ ๋ด๋ถ ๋ฉ์๋๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ด๋ถ ๋์๋ฐฉ์์ ์ค๋ช ํ๋ ์์ฌ์ฝ๋์ด๋ค.
- ํ๋กํผํฐ์ ์ข ๋ฅ๋ ๋ฐ์ดํฐ ํ๋กํผํฐ๊ฐ ์๊ณ , ์ ๊ทผ์ ํ๋กํผํฐ๊ฐ ์๋ค.
- ๋ฐ์ดํฐ ํ๋กํผํฐ์ ์ดํธ๋ฆฌ๋ทฐํธ(์์ฑ๊ฐ)๋ ๊ฐ์ฒด์ ํด๋น ํ๋กํผํฐ์ ๋ํ ์ญ์ , ์ถ๊ฐ, ๋ณ๊ฒฝ๋ฑ์ ๊ฐ๋ฅ ์ฌ๋ถ์ ๋ํด ์ ์ํ๋ค.
- ๊ฐ์ฒด์ ์๋ก์ด ํ๋กํผํฐ๊ฐ ์ถ๊ฐ๋ ๋๋ง๋ค ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ๋ด๋ถ์ ์ผ๋ก ํ๋กํผํฐ ์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ ์๋์ผ๋ก ์ ์ํ๋ค.
- ์ ๊ทผ์ ํ๋กํผํฐ๋ ์ ๊ทผ์ ํจ์๋ก ๊ตฌ์ฑ๋ ํ๋กํผํฐ๋ก, ๋ค๋ฅธ ๋ฐ์ดํฐ ํ๋กํผํฐ์ ๊ฐ์ ์ฝ๊ฑฐ๋ ๋ณ๊ฒฝํ ๋ ์ฐ์ธ๋ค.
์ด๋ฒ ํฌ์คํ
์ ๋ด๋ถ ์ฌ๋กฏ, ํ๋กํผํฐ ์ดํธ๋ฆฌ๋ทฐํธ๋ฑ ์์ํ ๊ฐ๋
์ด ๋์์ ์กฐ๊ธ ์ดํด๊ฐ ์ด๋ ค์ ๋ค.
๊ทธ๋๋ ํฌ์คํ
์ ์์ฑํ๋ฉด์ ํท๊ฐ๋ ธ๋ ๋ด์ฉ๋ค์ด ์กฐ๊ธ ์ ๋ฆฌ๊ฐ ๋ ๊ธฐ๋ถ์ด๋ค!
์๋ฐ์คํฌ๋ฆฝํธ์ ํต์ฌ์ธ ๊ฐ์ฒด์ธ ๋งํผ ์จ๊ฒจ์ง ๊ฐ๋ ๋ค์ด ๋ง์ ๊ฒ ๊ฐ๋ค. ์ฐจ๊ทผ์ฐจ๊ทผ ๊ณต๋ถํ๋ฉฐ ์ ๋ณตํด ๋ด์ผ์ง.