function Person(name) {
this.name = name;
}
// ํ๋กํ ํ์
๋ฉ์๋
Person.prototype.sayHello = function() {
console.log(`Hi My name is ${this.name}`)
};
const me = new Person('Lee')
// hasOwnProperty๋ Object.prototype์ ๋ฉ์๋๋ค.
console.log(me.hasOwnProperty('name')); // true
Person ์์ฑ์ ํจ์์ ์ํด ์์ฑ๋ me ๊ฐ์ฒด๋
Object.prototype
์ ๋ฉ์๋์ธhasOwnProperty
๋ฅผ ํธ์ถํ ์ ์๋ค. ์ด๊ฒ์ me ๊ฐ์ฒด๊ฐPerson.prototype
๋ฟ๋ง ์๋๋ผObject.prototype
๋ ์์๋ฐ์๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
Person.protype์ ํ๋กํ ํ์ ์Object.prototype
์ด๋ค. ํ๋กํ ํ์ ์ ํ๋กํ ํ์ ์ ์ธ์ ๋Object.prototype
์ด๋ค.
ํ๋กํ ํ์ ์ฒด์ธ์ด๋
์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๊ฐ์ฒด์ ํ๋กํผํฐ(๋ฉ์๋ ํฌํจ)์ ์ ๊ทผํ๋ ค๊ณ ํ ๋ ํด๋น ๊ฐ์ฒด์ ์ ๊ทผํ๋ ค๋ ํ๋กํผํฐ๊ฐ ์๋ค๋ฉด[[Prototype]]
๋ด๋ถ ์ฌ๋กฏ์ ์ฐธ์กฐ๋ฅผ ๋ฐ๋ผ ์์ ์ ๋ถ๋ชจ ์ญํ ์ ํ๋ ํ๋กํ ํ์ ์ ํ๋กํผํฐ๋ฅผ ์์ฐจ์ ์ผ๋ก ๊ฒ์ํ๋ ๊ฒ์ ๋งํ๋ค.
ํ๋กํ ํ์ ์ฒด์ธ
์ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ์์์ ๊ตฌํ ๋ฉ์ปค๋์ฆ์ด๋ค.
ํ๋กํ ํ์ ์ฒด์ธ
์ ์ต์์์ ์์นํ๋ ๊ฐ์ฒด๋ ์ธ์ ๋Object.prototype
์ด๋ค. ๋ฐ๋ผ์ ๋ชจ๋ ๊ฐ์ฒด๋Object.prototype
์ ์์ ๋ฐ๋๋ค.Object.prototype
์ ํ๋กํ ํ์ ์ฒด์ธ์ ์ข ์ ์ด๋ผ ํ๋ค.
ํ๋กํ ํ์ ์ฒด์ธ
์ ์์๊ณผ ํ๋กํผํฐ ๊ฒ์์ ์ํ ๋ฉ์ปค๋์ฆ์ด๋ค. ์ด์ ๋ฐํด ํ๋กํผํฐ๊ฐ ์๋ ์๋ณ์๋์ค์ฝํ ์ฒด์ธ
์์ ๊ฒ์์ค์ฝํ ์ฒด์ธ
์ ์๋ณ์ ๊ฒ์์ ์ํ ๋ฉ์ปค๋์ฆ์ด๋ค.
์ค์ฝํ ์ฒด์ธ
๊ณผํ๋กํ ํ์ ์ฒด์ธ
์ ์๋ก ์ฐ๊ด์์ด ๋ณ๋๋ก ๋์ํ๋ ๊ฒ์ด ์๋๋ผ ์๋ก ํ๋ ฅํ์ฌ ์๋ณ์ ์ ํ๋กํผํฐ๋ฅผ ๊ฒ์ํ๋ ๋ฐ ์ฌ์ฉ๋๋ค.
const Person = (function () {
// ์์ฑ์ ํจ์
function Person(name) {
this.name = name;
}
// ํ๋กํ ํ์
๋ฉ์๋
Person.prototype.sayHello = function () {
console.log(`Hi! My name is ${this.name}`);
};
// ์์ฑ์ ํจ์๋ฅผ ๋ฐํ
return Person;
}());
const me = new Person('Lee');
// ์ธ์คํด์ค ๋ฉ์๋
me.sayHello = function () {
console.log(`Hey! My name is ${this.name}`);
};
// ์ธ์คํด์ค ๋ฉ์๋๊ฐ ํธ์ถ๋๋ค. ํ๋กํ ํ์
๋ฉ์๋๋ ์ธ์คํด์ค ๋ฉ์๋์ ์ํด ๊ฐ๋ ค์ง๋ค.
me.sayHello(); // Hey! My name is Lee
ํ๋กํ ํ์ ์ด ์์ ํ ํ๋กํผํฐ(๋ฉ์๋ ํฌํจ)๋ฅผ ํ๋กํฌํ์ ํ๋กํผํฐ, ์ธ์คํด์ค๊ฐ ์์ ํ ํ๋กํผํฐ๋ฅผ ์ธ์คํด์ค ํ๋กํผํฐ๋ผ๊ณ ๋ถ๋ฅธ๋ค.
ํ๋กํ ํ์ ํ๋กํผํฐ์ ๊ฐ์ ์ด๋ฆ์ ํ๋กํผํฐ๋ฅผ ์ธ์คํด์ค์ ์ถ๊ฐํ๋ฉด ํ๋กํ ํ์ ์ฒด์ธ์ ๋ฐ๋ผ ํ๋กํ ํ์ ํ๋กํผํฐ๋ฅผ ๊ฒ์ํ์ฌ ํ๋กํ ํ์ ์ ํ๋กํผํฐ๋ฅผ ๋ฎ์ด์ฐ๋ ๊ฒ์ด ์๋๋ผ ์ธ์คํด์ค ํ๋กํผํฐ๋ก ์ถ๊ฐ.
์ด๋ ์ธ์คํด์ค ๋ฉ์๋ sayHello๋ ํ๋กํ ํ์ ๋ฉ์๋ sayHello๋ฅผ์ค๋ฒ๋ผ์ด๋ฉ
ํ๊ณ ํ๋กํ ํ์ ๋ฉ์๋ sayHello๋ ๊ฐ๋ ค์ง๋ค. ์ด์ฒ๋ผ ์์๊ด๊ณ์ ์ํด ํ๋กํผํฐ๊ฐ ๊ฐ๋ ค์ง๋ ํ์์ํ๋กํผํฐ ์๋์
์ด๋ผ ํ๋ค.
๐ก ์ค๋ฒ๋ผ์ด๋ฉ์ด๋?
์์ ํด๋์ค๊ฐ ๊ฐ์ง๊ณ ์๋ ๋ฉ์๋๋ฅผ ํ์ ํด๋์ค๊ฐ ์ฌ์ ์ํ์ฌ ์ฌ์ฉํ๋ ๋ฐฉ์
๐ ํ๋กํผํฐ๋ฅผ ์ญ์ ํ๋ ๊ฒฝ์ฐ
// ์ธ์คํด์ค ๋ฉ์๋๋ฅผ ์ญ์ ํ๋ค.
delete me.sayHello;
// ์ธ์คํด์ค์๋ sayHello ๋ฉ์๋๊ฐ ์์ผ๋ฏ๋ก ํ๋กํ ํ์
๋ฉ์๋๊ฐ ํธ์ถ๋๋ค.
me.sayHello(); // Hi! My name is Lee
์ ์ฝ๋๋ ํ๋กํ ํ์ ๋ฉ์๋๊ฐ ์๋ ์ธ์คํด์ค ๋ฉ์๋ sayHello๊ฐ ์ญ์ ๋๋ค.
๐ ๋ค์ ํ๋ฒ ํ๋กํผํฐ๋ฅผ ์ญ์
// ํ๋กํ ํ์
์ฒด์ธ์ ํตํด ํ๋กํ ํ์
๋ฉ์๋๊ฐ ์ญ์ ๋์ง ์๋๋ค.
delete me.sayHello;
// ํ๋กํ ํ์
๋ฉ์๋๊ฐ ํธ์ถ๋๋ค.
me.sayHell(); // Hi! My name is Lee
ํ์ ๊ฐ์ฒด๋ฅผ ํตํด ํ๋กํ ํ์ ์ ํ๋กํผํฐ๋ฅผ ๋ณ๊ฒฝ ๋๋ ์ญ์ ํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํ๋ค. ๋ค์ ๋งํด ํ์ ๊ฐ์ฒด๋ฅผ ํตํด get ์ก์ธ๋ ํ์ฉ๋๋ set ์ก์ธ์ค๋ ํ์ฉ๋์ง ์๋๋ค.
ํ๋กํ ํ์ ํ๋กํผํฐ๋ฅผ ๋ณ๊ฒฝ ๋๋ ์ญ์ ํ๋ ค๋ฉด ํ์ ๊ฐ์ฒด๋ฅผ ํตํด ํ๋กํ ํ์ ์ฒด์ธ์ผ๋ก ์ ๊ทผํ๋ ๊ฒ์ด ์๋๋ผ ํ๋กํ ํ์ ์ ์ง์ ์ ๊ทผํด์ผ ํ๋ค.
// ํ๋กํ ํ์
๋ฉ์๋ ๋ณ๊ฒฝ
Person.prototype.sayHello - function() {
console.log(`Hey! My name is ${this.name}`)
}
me.sayHello();
// ํ๋กํ ํ์
๋งค์๋ ์ญ์
delete Person.prototype.sayHello;
me.sayHello(); // TypeError: me.sayHello is not a function
ํ๋กํ ํ์ ์ ์์์ ๋ค๋ฅธ ๊ฐ์ฒด๋ก ๋ณ๊ฒฝํ ์ ์๋ค ์ด๊ฒ์ ๋ถ๋ชจ ๊ฐ์ฒด์ธ ํ๋กํ ํ์ ์ ๋์ ์ผ๋ก ๋ณ๊ฒฝํ ์ ์๋ค๋ ๊ฒ์ ์๋ฏธ.์ด๋ฌํ ํน์ง์ ํ์ฉํ์ฌ ๊ฐ์ฒด๊ฐ์ ์์ ๊ด๊ณ๋ฅผ ๋์ ์ผ๋ก ๋ณ๊ฒฝํ ์ ์๋ค.
const Person = (function () {
function Person(name) {
this.name = name;
}
// โ ์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ๋ฅผ ํตํด ํ๋กํ ํ์
์ ๊ต์ฒด
Person.prototype = {
sayHello() {
console.log(`Hi! My name is ${this.name}`);
}
};
return Person;
}());
const me = new Person('Lee');
โ ์์ person.prototypep์ ๊ฐ์ฒด ๋ฆฌํฐ๋ด ํ ๋น ์ด๋ Person ์์ฑ์ ํจ์๊ฐ ์์ฑํ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ ๊ฐ์ฒด ๋ฆฌํฐ๋ด๋ก ๊ต์ฒดํ ๊ฒ์ด๋ค.
ํ๋กํ ํ์ ์ผ๋ก ๊ต์ฒดํ ๊ฐ์ฒด ๋ฆฌํฐ๋ด์๋ constructor ํ๋กํผํฐ๊ฐ ์๋ค. ๋ฐ๋ผ์ me ๊ฐ์ฒด์ ์์ฑ์ ํจ์๋ฅผ ๊ฒ์ํ๋ฉด Person์ด ์๋ Object๊ฐ ๋์จ๋ค.
// ํ๋กํ ํ์
์ ๊ต์ฒดํ๋ฉด constructor ํ๋กํผํฐ์ ์์ฑ์ ํจ์ ๊ฐ์ ์ฐ๊ฒฐ์ด ํ๊ดด๋๋ค.
console.log(me.constructor === Person); // false
// ํ๋กํ ํ์
์ฒด์ธ์ ๋ฐ๋ผ Object.prototype์ constructor ํ๋กํผํฐ๊ฐ ๊ฒ์๋๋ค.
console.log(me.constructor === Object); // true
ํ๊ดด๋ constructor ํ๋กํผํฐ์ ์์ฑ์ ํจ์ ๊ฐ์ ์ฐ๊ฒฐ ๋์ด๋ฆฌ๊ธฐ
const Person = (function () {
function Person(name) {
this.name = name;
}
// ์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ๋ฅผ ํตํด ํ๋กํ ํ์
์ ๊ต์ฒด
Person.prototype = {
// constructor ํ๋กํผํฐ์ ์์ฑ์ ํจ์ ๊ฐ์ ์ฐ๊ฒฐ์ ์ค์
constructor: Person,
sayHello() {
console.log(`Hi My name is ${this.name}`)
}
};
return Person;
}());
const me = new Person('Lee');
// constructor ํ๋กํผํฐ๊ฐ ์์ฑ์ ํจ์๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
console.log(me.constructor === Person); // true
console.log(me.constructor === Object); // false
์ธ์คํด์ค
__proto__ ์ ๊ทผ์ ํ๋กํผํฐ
๋๋Object.getPrototypeOf ๋ฉ์๋
๋ฅผ ํตํด ์ ๊ทผํ ์ ์์ผ๋ฉฐ ๊ต์ฒดํ ์ ์๋ค.
์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ์ ๋ค๋ฅธ ์์์ ๊ฐ์ฒด๋ฅผ ๋ฐ์ธ๋ฉํ๋ ๊ฒ์ ๋ฏธ๋์ ์์ฑํ ์ธ์คํด์ค์ ํ๋กํ ํ์ ์ ๊ต์ฒดํ๋ ๊ฒ.__prototype__ ์ ๊ทผ์ ํ๋กํผํฐ
๋ฅผ ํตํด ํ๋กํ ํ์ ์ ๊ต์ฒดํ๋ ๊ฒ์ ์ด๋ฏธ ์์ฑ๋ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ ๊ต์ฒดํ๋ ๊ฒ.
function Person(name) {
this.name = name;
}
const me = new Person('Lee');
// ํ๋กํ ํ์
์ ๊ต์ฒดํ ๊ฐ์ฒด
const parent = {
sayHello() {
console.log(`Hi! My name is ${this.name}`);
}
};
// โ me ๊ฐ์ฒด์ ํ๋กํ ํ์
์ parent ๊ฐ์ฒด๋ก ๊ต์ฒดํ๋ค.
Object.setPrototypeOf(me, parent);
// ์ ์ฝ๋๋ ์๋์ ์ฝ๋์ ๋์ผํ๊ฒ ๋์ํ๋ค.
// me.__proto__ = parent;
me.sayHello(); // Hi! My name is Lee
โ ์์ me ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ parent ๊ฐ์ฒด๋ก ๊ต์ฒด
// ํ๋กํ ํ์
์ ๊ต์ฒดํ๋ฉด constructor ํ๋กํผํฐ์ ์์ฑ์ ํจ์ ๊ฐ์ ์ฐ๊ฒฐ์ด ํ๊ดด๋๋ค.
console.log(me.constructor === Person); // false
console.log(me.constructor === Object); // true
๐ ์์ฑ์ ํจ์์ ์ํ ํ๋กํ ํ์
๊ต์ฒด vs ์ธ์คํด์ค์ ์ํ ํ๋กํ ํ์
๊ต์ฒด
๐ ์์ฑ์ ํจ์์ ์ํ ํ๋กํ ํ์ ๊ต์ฒด vs ์ธ์คํด์ค์ ์ํ ํ๋กํ ํ์ ๊ต์ฒด
function Person(name) {
this.name = name;
}
// ํ๋กํ ํ์
์ผ๋ก ๊ต์ฒดํ ๊ฐ์ฒด
const person = {
// constructor ํ๋กํผํฐ์ ์์ฑ์ ํจ์ ๊ฐ์ ์ฐ๊ฒฐ์ ์ค์
constructor : Person,
sayHello() {
console.log(`Hi! My name is ${this.name}`);
}
};
// ์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ์ ํ๋กํ ํ์
๊ฐ์ ์ฐ๊ฒฐ์ ์ค์
Person.prototype = parent;
// me ๊ฐ์ฒด์ ํ๋กํ ํ์
์ parent ๊ฐ์ฒด๋ก ๊ต์ฒดํ๋ค.
Object.setPrototypeOf(me, parent);
// ์ ์ฝ๋๋ ์๋์ ์ฝ๋์ ๋์ผํ๊ฒ ๋์ํ๋ค.
// me.__proto__ = parent;
me.sayHello(); // Hi! My name is Lee
// constructor ํ๋กํผํฐ๊ฐ ์์ฑ์ ํจ์๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
console.log(me.constructor === Person); // true
console.log(me.constructor === Object); // false
// ์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ๊ฐ ๊ต์ฒด๋ ํ๋กํ ํ์
์ ๊ฐ๋ฆฌํจ๋ค.
console.log(Person.prototype === Obejct.getPrototypeOf(me)); // true
instanceof ์ฐ์ฐ์
๋ ์ดํญ ์ฐ์ฐ์๋ก ์ข๋ณ์ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋, ์ฐ๋ณ์ ์์ฑ์ ํจ์๋ฅผ ๊ฐ๋ฆฌํค๋ ์๋ณ์๋ฅผ ํผ์ฐ์ฐ์๋ก ๋ฐ๋๋ค. ๋ง์ฝ ์ฐ๋ณ์ ํผ์ฐ์ฐ์๊ฐ ํจ์๊ฐ ์๋ ๊ฒฝ์ฐ TypeError๊ฐ ๋ฐ์.
๊ฐ์ฒด instanceof ์์ฑ์ ํจ์
์ฐ๋ณ์ ์์ฑ์ ํจ์์ prototype์ ๋ฐ์ธ๋ฉ๋ ๊ฐ์ฒด๊ฐ ์ข๋ณ์ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ฒด์ธ ์์ ์กด์ฌํ๋ฉด true๋ก ํ๊ฐ ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ false๋ก ํ๊ฐ
// ์์ฑ์ ํจ์
function Person(name) {
this.name = name;
}
const me = new Person('Lee');
// Person.prototype์ด me ๊ฐ์ฒด์ ํ๋กํ ํ์
์ฒด์ธ ์์ ์กด์ฌํ๋ฏ๋ก true๋ก ํ๊ฐ
console.log(me instanceof Person); // true
// Object.prototype์ด me ๊ฐ์ฒด์ ํ๋กํ ํ์
์ฒด์ธ ์์ ์กด์ฌํ๋ฏ๋ก true๋ก ํ๊ฐ
console.log(me instanceof Object); // true
instanceof ์ฐ์ฐ์
๋ ์์ฑ์ ํจ์์ prototype์ ๋ฐ์ธ๋ฉ๋ ๊ฐ์ฒด๊ฐ ํ๋กํ ํ์ ์ฒด์ธ ์์ ์กด์ฌํ๋์ง ํ์ธํ๋ค.
constructor ํ๋กํผํฐ์ ์์ฑ์ ํจ์ ๊ฐ์ ์ฐ๊ฒฐ์ด ํ๊ดด๋์ด๋ instanceof๋ ์๋ฌด๋ฐ ์ํฅ์ ๋ฐ์ง ์๋๋ค. ์ค์ง ํ๋กํ ํ์ ์ฒด์ธ ์์์๋ง ๋ณด๊ธฐ ๋๋ฌธ
Object.create ๋ฉ์๋
๋ ๋ช ์์ ์ผ๋ก ํ๋กํ ํ์ ์ ์ง์ ํ์ฌ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑ.Object.create ๋ฉ์๋
๋ ๋ค๋ฅธ ๊ฐ์ฒด ์์ฑ ๋ฐฉ์๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์ถ์ ์ฐ์ฐOrdinarayObjectCreate
๋ฅผ ํธ์ถํ๋ค.
Object.create ๋ฉ์๋
์ ์ฒซ ๋ฒ์งธ ๋งค๊ฐ๋ณ์์๋ ์์ฑํ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ผ๋ก ์ง์ ํ ๊ฐ์ฒด๋ฅผ ์ ๋ฌ
Object.create ๋ฉ์๋
์ ๋ ๋ฒ์ฌ ๋งค๊ฐ๋ณ์์๋ ์์ฑํ ๊ฐ์ฒด์ ํ๋กํผํฐ ํค์ ํ๋กํผํฐ ๋์คํฌ๋ฆฝํฐ ๊ฐ์ฒด๋ก ์ด๋ค์ง ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๋ค.
// ํ๋กํ ํ์
์ด null์ธ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค. ์์ฑ๋ ๊ฐ์ฒด๋ ํ๋กํ ํ์
์ฒด์ธ์ ์ข
์ ์ ์์น.
// obj -> null
let obj = Object.create(null);
console.log(Object.getPrototypeOf(obj) === null); // true
// Object.prototype์ ์์๋ฐ์ง ๋ชปํ๋ค.
console.log(obj.toString()); // TypeError: obj.toString is not a function
// obj -> Object.prototype -> null
// obj = {};์ ๋์ผํ๋ค.
obj = Object.create(Object.proototype);
console.log(Object.getProitotypeOf(obj) === Object.prototype); // true
// obj -> Object.prototype -> null
// obj = {};์ ๋์ผํ๋ค
obj = Object.create(Object.prototype);
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true
// obj -> Object.prototype -> null
// obj = { x: 1 };์ ๋์ผํ๋ค.
obj = Object.create(Object.prototype, {
x: {value: 1, writable: true, enumerable: true, configurable: ture }
});
// ์ ์ฝ๋๋ ์๋์ ๋์ผํ๋ค.
// obj = Object.create(Object.prototype);
// obj.x = 1;
console.log(obj.x); // 1
console.log(Object.getPrototypeof(obj) === Object.prototype); // true
const myProto = { x: 10 };
// ์์์ ๊ฐ์ฒด๋ฅผ ์ง์ ์์๋ฐ๋๋ค.
// obj -> myProto -> Object.prototype -> null
obj = Object.create(myProto);
console.log(obj.x); // 10
console.log(Object.getPrototypeOf(obj) === myProto); // true
// ์์ฑ์ ํจ์
function Person(name) {
this.name = name;
}
// obj -> Person.prototype -> Objectprototype -> null
// obj = new Person('Lee')์ ๋์ผํ๋ค.
obj = Object.create(Person.prototype);
obj.name = 'Lee'
console.log(obj.name); // Lee
console.log(Object.getPrototypeOf(obj) === Person.prootype); // true
๐ object.create ๋ฉ์๋
์ ์ฅ์
- new ์ฐ์ฐ์๊ฐ ์์ด๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์๋ค.
- ํ๋กํ ํ์ ์ ์ง์ ํ๋ฉด์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์๋ค.
- ๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ์ํด ์์ฑ๋ ๊ฐ์ฒด๋ ์์๋ฐ์ ์ ์๋ค.
โ Object.prototype
์ ๋นํธ์ธ ๋ฉ์๋๋ฅผ ๊ฐ์ฒด๊ฐ ์ง์ ํธ์ถํ๋ ๊ฒ ๊ถ์ฅํ์ง ์๋๋ค.
Object.create
๋ฉ์๋๋ฅผ ํตํด ํ๋กํ ํ์ ์ฒด์ธ์ ์ข ์ ์ ์์นํ๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์๊ธฐ ๋๋ฌธ
// ํ๋กํ ํ์
์ด null์ธ ๊ฐ์ฒด, ์ฆ ํ๋กํ ํ์
์ฒด์ธ์ ์ข
์ ์ ์์นํ๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
const obj = Object.create(null);
obj.a = 1;
console.log(Object.getPrototypeOf(obj) === null); // true
// obj๋ Object.prototype์ ๋นํธ์ธ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
console.log(obj.hasOwnProperty('a'));
// TypeError: obj.hasOwnProperty is not a function
// ์์ ๊ฐ์ TypeError๋ฅผ ๋ฐ์์ํฌ ์ํ ์์ ๊ธฐ ์ํด Object.prototype์ ๋นํธ์ธ ๋ฉ์๋ ์ง์ ํธ์ถ.
// Object.prototype์ ๋นํธ์ธ ๋ฉ์๋๋ ๊ฐ์ฒด๋ก ์ง์ ํธ์ถํ์ง ์๋๋ค.
console.log(Object.prototype.hasOwnProperty.call(obj, 'a')); // true
__proto__
์ ์ํ ์ง์ ์์๊ฐ์ฒด ๋ฆฌํฐ๋ด ๋ด๋ถ์์
__proto__
์ ๊ทผ์ ํ๋กํฐํผ๋ฅผ ์ฌ์ฉํ์ฌ ์ง์ ์์ ๊ตฌํํ ์ ์๋ค.
const myProto = { x: 10 };
// ๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ์ํด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฉด์ ํ๋กํ ํ์
์ ์ง์ ํ์ฌ ์ง์ ์์๋ฐ์ ์ ์๋ค,
const obj = {
y: 20,
// ๊ฐ์ฒด๋ฅผ ์ง์ ์์๋ฐ๋๋ค.
// obj -> myProto -> Object.prototype -> null
__proto__: myProto
};
/* ์ ์ฝ๋ ์๋์ ๋์ผ
const obj = Object.create(myProto, {
y: {value: 20, writable: true, enumerable: true, configurable: true}
});
*/
console.log(obj.x, obj.); // 10 20
console.log(Object.getPrototypeOf(obj) === myProto); // true
์ ์ ํ๋กํผํฐ / ๋ฉ์๋
๋ ์์ฑ์ ํจ์๋ก ์ธ์คํด์ค๋ฅผ ์์ฑํ์ง ์์๋ ์ฐธ์กฐ / ํธ์ถ ํ ์ ์๋ ํ๋กํผํฐ / ๋ฉ์๋๋ฅผ ๋งํ๋ค.
// ์์ฑ์ ํจ์
fucntion Person(name) {
this.name = name;
}
// ํ๋กํ ํ์
๋ฉ์๋
Person.prototype.sayHello = fucntion() {
console.log(`Hi! My name is ${this.name}`)
};
// ์ ์ ํ๋กํผํฐ
Person.staticProp = 'static prop'
// ์ ์ ๋ฉ์๋
Person.staticMethod = function () {
console.log('staticMethod');
}
const me = new Person('Lee');
// ์์ฑ์ ํจ์ ์ถ๊ฐํ ์ ์ ํ๋กํผํฐ / ๋ฉ์๋๋ ์์ฑ์ ํจ์๋ก ์ฐธ์กฐ / ํธ์ถ ํ๋ค.
Person.staticMethod(); // staticMethod
// ์ ์ ํ๋กํผํฐ / ๋ฉ์๋๋ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค๋ก ์ฐธ์กฐ / ํธ์ถํ ์ ์๋ค.
// ์ธ์คํด์ค๋ก ์ฐธ์กฐ / ํธ์ถํ ์ ์๋ ํ๋กํผํฐ / ๋ฉ์๋๋ ํ๋กํ ํ์
์ฒด์ธ์์ ์กด์ฌํด์ผ ํ๋ค.
me.staticMethod(); // TypeError: me.staticMethod is not a function
// Object.create๋ ์ ์ ๋ฉ์๋๋ค.
const obj = Object.create({ name: 'noh'});
// Object.prototype.hasOwnProperty๋ ํ๋กํ ํ์
๋ฉ์๋๋ค.
obj.hasOwnProperty('name'); // false
Object.create
๋ฉ์๋๋ ์ ์ ๋ฉ์๋์ด๊ณ ,Obejct.prototype.hasOwnproperty
๋ฉ์๋๋ ํ๋กํ ํ์ ์ ๋ฉ์๋์ด๋ค.
// ์ธ์คํด์ค / ํ๋กํ ํ์
๋ฉ์๋ ๋ด์์ this๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค๋ฉด ๊ทธ ๋ฉ์๋๋ ์ ์ ๋ฉ์๋๋ก ๋ณ๊ฒฝํ ์ ์๋ค.
function Foo() {}
// ํํ ํ ํ์
๋ฉ์๋
// this๋ฅผ ์ฐธ์กฐํ์ง ์๋ ํ๋กํ ํ์
๋ฉ์๋๋ ์ ์ ๋ฉ์๋๋ก ๋ณ๊ฒฝํ์ฌ๋ ๋์ผํ ํจ๊ณผ๋ฅผ ์ป์ ์ ์๋ค.
Foo.prototype.x = function () {
conosole.log('x');
}
const foo = new Foo();
// ํ๋กํ ํ์
๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ์ธ์คํด์ค๋ฅผ ์์ฑํด์ผ ํ๋ค.
foo.x(); // x
// ์ ์ ๋ฉ์๋
Foo.x = function () {
console.log('x');
}
// ์ ์ ๋ฉ์๋๋ ์ธ์คํด์ค๋ฅผ ์์ฑํ์ง ์์๋ ํธ์ถํ ์ ์๋ค.
Foo.x(); // x
in ์ฐ์ฐ์
๋ ๊ฐ์ฒด ๋ด์ ํน์ ํ๋กํผํฐ๊ฐ ์กด์ฌํ๋์ง ์ฌ๋ถ๋ฅผ ํ์ธํ๋ค.
// ์ฌ์ฉ๋ฒ
/**
* key: ํ๋กํผํฐ ํค๋ฅผ ๋ํ๋ด๋ ๋ฌธ์์ด
* object: ๊ฐ์ฒด๋ก ํ๊ฐ๋๋ ํํ์
* */
key in object
const person = {
name: "noh",
address: "Seoul",
};
// person ๊ฐ์ฒด์ name ํ๋กํผํฐ ์กด์ฌ
console.log('name' in person); // true
// person ๊ฐ์ฒด์ address ํ๋กํผํฐ ์กด์ฌ
console.log('address' in person); // true
// person ๊ฐ์ฒด์ age ํ๋กํผํฐ๊ฐ ์กด์ฌํ์ง ์๋๋ค.
console.log('age' in person); // fasle
in ์ฐ์ฐ์
๋ ํ์ธ ๋์ ๊ฐ์ฒด๊ฐ ์์๋ฐ์ ๋ชจ๋ ํ๋กํ ํ์ ์ ํ๋กํผํฐ๋ฅผ ํ์ธํ๋ฏ๋ก ์ฃผ์๊ฐ ํ์.
console.log('toString' in person); // true
in ์ฐ์ฐ์
๊ฐ person ๊ฐ์ฒด๊ฐ ์ํ ํ๋กํ ํ์ ์ฒด์ธ ์์ ์กด์ฌํ๋ ๋ชจ๋ ํ๋กํ ํ์ ์์ toString ํ๋กํผํฐ๋ฅผ ๊ฒ์ํ๊ธฐ ๋๋ฌธ. toString์Object.prototype
์ ๋ฉ์๋
๐ก Reflect.has ๋ฉ์๋
ES6 ์์ ๋์ ๋์๊ณ ,
in ์ฐ์ฐ์
์ ๋์ผํ๊ฒ ๋์.
const person = { name: 'Lee' };
console.log(Reflect.has(person, 'name')); // true
console.log(Reflect.has(person, 'toString)); // true
Object.prototype.hasOwnProperty ๋ฉ์๋
๋ฅผ ์ฌ์ฉํด๋ ๊ฐ์ฒด์ ํน์ ํ๋กํผํฐ๊ฐ ์กด์ฌํ๋์ง ํ์ธํ ์ ์์.
์ธ์๋ก ์ ๋ฌ๋ฐ์ ํ๋กํผํฐ ํค๊ฐ ๊ฐ์ฒด ๊ณ ์ ์ ํ๋กํผํฐ ํค์ธ ๊ฒฝ์ฐ์๋ง true๋ฅผ ๋ฐํ ์์๋ฐ์ ํ๋กํ ํ์ ์ ํ๋กํผํฐ ํค์ธ ๊ฒฝ์ฐ false๋ฅผ ๋ฐํ.
console.log(person.hasOwnProperty('name')); // true
console.log(person.hasOwnProperty('age')); // false
console.log(person.hasOwnProperty('toString')); // false
๊ฐ์ฒด์ ๋ชจ๋ ํ๋กํผํฐ๋ฅผ ์ํํ๋ฉฐ ์ด๊ฑฐํ๋ ค๋ฉด
for...in
๋ฌธ์ ์ฌ์ฉ.
for (๋ณ์์ ์ธ๋ฌธ in ๊ฐ์ฒด) {...}
const person = {
name: 'noh',
address: 'Seouol'
};
// for...in ๋ฌธ์ ๋ณ์ prop์ person ๊ฐ์ฒด์ ํ๋กํผํฐ ํค๊ฐ ํ ๋น๋๋ค.
for(const key in person) {
console.log(key + ':' + person[key]);
}
// name: noh
// address: Seoul
for...in ๋ฌธ
์ ๊ฐ์ฒด์ ํ๋กํผํฐ ๊ฐ์๋ง ํผ ์ํ ๋ณ์ ์ ์ธ๋ฌธ์์ ์ ์ธํ ๋ณ์์ ํ๋กํผํฐ ํค๋ฅผ ํ ๋นํ๋ค.
for...in ๋ฌธ
์ ์์๋ฐ์ ํ๋กํ ํ์ ์ ํ๋กํผํฐ๊น์ง ์ด๊ฑฐํ๋ค.
const person = {
name: "noh",
address: "Seoul"
};
// in ์ฐ์ฐ์๋ ๊ฐ์ฒด๊ฐ ์์๋ฐ์ ๋ชจ๋ ํ๋กํ ํ์
์ ํ๋กํผํฐ๋ฅผ ํ์ธํ๋ค.
console.log('toString' in person); // true
// for...in ๋ฌธ๋ ๊ฐ์ฒด๊ฐ ์์๋ณด๋ค์ ๋ชจ๋ ํ๋กํ ํ์
์ ํ๋กํผํฐ๋ฅผ ์ด๊ฑฐํ๋ค.
// ํ์ง๋ง toString๊ณผ ๊ฐ์ Object.prototype์ ํ๋กํผํฐ๊ฐ ์ด๊ฑฐ๋์ง ์๋๋ค.
for(const key in person) {
console.log(key + ':' + person[key])
}
// name: "noh"
// address: "Seoul"
toString ๋ฉ์๋๊ฐ ์ด๊ฑฐํ ์ ์๋๋ก ์ ์๋์ด ์๋ ํ๋กํผํฐ์ด๊ธฐ ๋๋ฌธ ๋ค์ ๋งํด,
Object.prototype.string
ํ๋กํผํฐ์ ํ๋กํผํฐ ์ดํธ๋ฆฌ๋ทฐํธ[[Enumerable]]
์ ๊ฐ์ด false์ด๊ธฐ ๋๋ฌธ.
for...in ๋ฌธ
์ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ฒด์ธ ์์ ์กด์ฌํ๋ ๋ชจ๋ ํ๋กํ ํ์ ์ ํ๋กํผํฐ ์ค์์ ํ๋กํผํฐ ์ดํธ๋ฆฌ๋ทฐํธ [[Emumerable]]์ ๊ฐ์ด true์ธ ํ๋กํผํฐ๋ฅผ ์ํํ๋ฉฐ ์ด๊ฑฐํ๋ค.
const person = {
name: 'noh',
address: 'Seoul',
__proto__: { age: 20}
};
for (const key in person) {
console.log(key + ":" + person[key]);
}
// name: noh
// address: Seoul
// age: 20
for ... in
๋ฌธ์ ํ๋กํผํฐ ํค๊ฐ ์ฌ๋ฒ์ธ ํ๋กํผํฐ๋ ์ด๊ฑฐํ์ง ์๋๋ค.
const sym = Symbol();
const obj = {
a: 1,
[sym]: 10
};
for (const key in obj) {
console.log(key + ": " + obj[key]);
}
// a : 1
์์๋ฐ์ ํ๋กํผํฐ ์ ์ธ ๊ฐ์ฒด ์์ ์ ํ๋กํผํฐ๋ง ์ด๊ฑฐํ๋ ค๋ฉด
Obejct.prototype.hasOwnproperty ๋ฉ์๋
๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด ์์ ์ ํ๋กํผํฐ์ธ์ง ํ์ธ.
const person = {
name: 'noh',
address: 'Seoul',
__proto__: { age: 20}
};
for (const key in personb) {
// ๊ฐ์ฒด ์์ ์ ํ๋กํผํฐ์ธ์ง ํ์ธ
if(!person.hasOwnProperty(key)) contineu;
console.log(key + ':' + person[pkey]);
}
// name: noh
// address : Seoul
๋ฐฐ์ด์๋
for...in
๋ฌธ์ ์ฌ์ฉํ์ง ๋ง๊ณfor
๋ฌธfor...of
๋ฌธ ๋๋Array.prototype.forEach
๋ฉ์๋๋ฅผ ์ฌ์ฉํ๊ธฐ๋ฅผ ๊ถ์ฅ. ์ฌ์ค ๋ฐฐ์ด๋ ๊ฐ์ฒด์ด๋ฏ๋ก ํ๋กํผํฐ์ ์์๋ฐ์ ํ๋กํผํฐ๊ฐ ํฌํจ๋ ์ ์๋ค.
const arr = [1, 2, 3];
arr.x = 10; // ๋ฐฐ์ด๋ ๊ฐ์ฒด์ด๋ฏ๋ก ํ๋กํผํฐ๋ฅผ ๊ฐ์ง ์ ์๋ค.
for (const i in arr) {
// ํ๋กํผํฐ x๋ ์ถ๋ ฅ๋๋ค.
console.log(arr[i]); // 1 2 3 10
};
// arr.length๋ 3์ด๋ค.
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]); // 1 2 3
}
// forEach ๋ฉ์๋๋ ์์๊ฐ ์๋ ํ๋กํผํฐ๋ ์ ์ธํ๋ค.
arr.forEach(v => console.log(v)); // 1 2 3
// for...of๋ ๋ณ์ ์ ์ธ๋ฌธ์์ ์ ์ธํ ๋ณ์์ ํค๊ฐ ์๋ ๊ฐ์ ํ ๋นํ๋ค.
for (const value of arr) {
console.log(value); // 1 2 3
};
๊ฐ์ฒด ์์ ์ ๊ณ ์ ํ๋กํผํฐ๋ง ์ด๊ฑฐํ๊ธฐ ์ํด์๋
for ... in
๋ฌธ์ ์ฌ์ฉํ ๊ฒ๋ณด๋ค Object.keys / values / entries ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํ๋ค.
โ Object.keys
๊ฐ์ฒด ์์ ์ ์ด๊ฑฐ ๊ฐ๋ฅํ ํ๋กํผํฐ ํค๋ฅผ ๋ฐฐ์ด๋ก ๋ฐํํ๋ค.
const person = {
name: "noh",
address: "Seoul",
__proto__: { age: 20 }
};
console.log(Object.keys(person)); // {"name", "address"}
โ Object.values
ES8์์ ๋์ ๋์๊ณ ๊ฐ์ฒด ์์ ์ ์ด๊ฑฐ ๊ฐ๋ฅํ ํ๋กํผํฐ ๊ฐ์ ๋ฐฐ์ด๋ก ๋ฐํ.
console.log(Object.values(person)); // ["noh", "Seoul"]
โ Object.entries
ES8์์ ๋์ ๋์๊ณ ๊ฐ์ฒด ์์ ์ ์ด๊ฑฐ ๊ฐ๋ฅํ ํ๋กํผํฐ ํค์ ๊ฐ์ ์์ ๋ฐฐ์ด์ ๋ฐฐ์ด์ ๋ด์ ๋ฐํ.
console.log(Object.entries(person)); // ["name", "noh"], ["address", "Seoul"]
Object.entries(person).forEach(([key, value]) => console.log(key, value));
/*
'name' 'noh'
'address' 'Seoul'
*/