6/ OOP (ES5 ๊ธฐ์ค)
๐ ์ธ์ฌ์ด๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ค ๋ฉ๋ชจํด์ผํ ๋ถ๋ถ๋ง ์ ์์ต๋๋ค.
0. ํด๋์ค ๊ธฐ๋ฐ์ ์ธ์ด - ํ๋กํ ํ์ ๊ธฐ๋ฐ์ ์ธ์ด #### ํด๋์ค ๊ธฐ๋ฐ์ ์ธ์ด - ํด๋์ค๋ก ๊ฐ์ฒด์ ๊ธฐ๋ณธ์ ์ธ
ํํ์ ๊ธฐ๋ฅ์ ์ ์ํ๊ณ , ์์ฑ์๋ก ์ธ์คํด์ค๋ฅผ ๋ง๋ค์ด์ ์ฌ์ฉํ ์ ์๋ค. - ๋ฐํ์์ ๋ฐ๊ฟ ์ ์๋ค. - ์ ํ์ฑ, ์์ ์ฑ, ์์ธก์ฑ๋ฑ์ ๊ด์ ์์๋ ํ๋กํ ํ์ ๊ธฐ๋ฐ์ ์ธ์ด๋ณด๋ค ์ข๋ ๋์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฅ. - JAVA, C++
ํ๋กํ ํ์ ๊ธฐ๋ฐ์ ์ธ์ด
- ๊ฐ์ฒด์ ์๋ฃ๊ตฌ์กฐ, ๋ฉ์๋ ๋ฑ์ ๋์ ์ผ๋ก ๋ฐ๊ฟ ์ ์๋ค.
- ์๋ฐ์คํฌ๋ฆฝํธ
1. ํด๋์ค, ์์ฑ์, ๋ฉ์๋
function Person(arg) {
// ํด๋์ค์ด์, ์์ฑ์์ ์ญํ ์ ํจ.
this.name = arg;
this.getName = function () {
return this.name;
};
this.setName = function (value): void {
this.name = value;
};
}
const me = new Person('Kim');
console.log(me.getName()); // Kim
me.setName('Joy');
console.log(me.getName()); // Joyconst you = new Person('Gray');
const him = new Person('Lee');- ๊ณตํต์ ์ผ๋ก ์ฌ์ฉ๋ ์ ์๋ setName๊ณผ getName ๋ฉ์๋๊ฐ ์ค๋ณต์ผ๋ก ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ ค๋๊ฒ ๋๋ค.
- setName๊ณผ getName์ ์ฌ์ฌ์ฉํ์!
function Person(arg) {
this.name = arg;
}
Person.prototype.getName = function () {
return this.name;
};
Person.prototype.setName = function (value) {
this.name = value;
};
const you = new Person('Gray');
const him = new Person('Lee');
console.log(you.getName()); // this๋ ์์ ์ ํธ์ถํ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋๋ค.
console.log(him.getName()); // ํ๋กํ ํ์
์ฒด์ธ์ผ๋ก ์ ๊ทผํ ์ ์๋ค.ํ๋กํ ํ์ ๋ฉ์๋๋ฅผ ๋ง๋๋ ๋ฃจํด์ ํจ์์ฒด์ธ์ ๋ ์์์ธ Function ํ๋กํ ํ์ ์ method๋ผ๋ ์ด๋ฆ์ผ๋ก ๋ง๋ค์ด๋๊ณ ์ฌ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ ์๋ค.
Function.prototype.method = function(name, function) {
if(!this.prototpye[name]) {
this.prototype[name] = function;
}// ํ๋กํ ํ์
์ ๊ฐ์ ์ด๋ฆ์ ๋ฉ์๋๊ฐ ์๋ค๋ฉด
}
function Person(arg) {
this.name = arg;
}
Person.method('setName', function(value){
this.name = value;
})
Person.method('getName', function() {
return this.name;
})
const me = new Person("me");
const you = new Person("you");
console.log(me.getName());
console.log(you.getName());2. ์์ - ์๋ฐ์คํฌ๋ฆฝํธ๋ ํด๋์ค๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ์ ํต์ ์ธ ์์์ ์ง์ํ์ง ์๋๋ค. - ์๋ฐ์คํฌ๋ฆฝํธ
ํน์ฑ ์ค ๊ฐ์ฒด ํ๋กํ ํ์ ์ฒด์ธ์ ์ด์ฉํ์ฌ ์์์ ๊ตฌํํด๋ผ ์ ์๋ค.
์์ ๊ตฌํ๋ฐฉ๋ฒ
- ํด๋์ค ๊ธฐ๋ฐ ์ ํต์ ์ธ ์์ ๋ฐฉ์์ ํ๋ด๋ (์ปจํ ์คํธ ์์ฒด๋ฅผ ์์๋ฐ์)
- ํด๋์ค ๊ฐ๋ ์์ด ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ผ๋ก ์์์ ๊ตฌํํ๋ ๋ฐฉ์ => Prototypeal inheritance
2-1. ํ๋กํ ํ์ ์ ์ด์ฉํ ์์
function create_object(o) {
function F() {}
F.prototype = o;
return new F();
} // Object.create() ํจ์๋ก ์ ๊ณต๋๋ค.์ธ์๋ก ๋ค์ด์จ ๊ฐ์ฒด(o)๋ฅผ ๋ถ๋ชจ๋ก ํ๋ ์์ ๊ฐ์ฒด(F)๋ฅผ ์์ฑํ์ฌ ๋ฐํํ๋ค. => ํ๋กํ ํ์ ์ ํน์ฑ์ ํ์ฉํ์ฌ ์์์ ๊ตฌํํ๋๊ฒ = ํ๋กํ ํ์ ๊ธฐ๋ฐ์ ์์
์์
function create_object(o) {
function F() {}
F.prototype = o;
return new F();
}
var person = {
name: "Joy"
getName: function() { // ES6์ getter ๊ฐ๋
return this.name;
}
setName: function(arg){ // ES6์ setter ๊ฐ๋
this.name = arg;
}
}
var me = create_object(person)
me.name // Joy
me.getName() // Joy
me.setName("Kim")
me.name // Kim
me.getName() // Kim- ํด๋์ค์ ํด๋นํ๋ ์์ฑ์ ํจ์๋ฅผ ๋ง๋ค์ง๋ ์์๊ณ ,
- ๊ทธ ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ๋ฐ๋ก ์์ฑํ์ง๋ ์์๋ค.
- person ๊ฐ์ฒด์ ์ด ๊ฐ์ฒด๋ฅผ ํ๋กํ ํ์ ์ฒด์ธ์ผ๋ก ์ฐธ์กฐํ ์ ์๋ ์์ ๊ฐ์ฒด me๋ฅผ ๋ง๋ค์ด์ ์ฌ์ฉํจ.
me.setAge = function(age) {...}
me.getAge = function() {...}์์ ๋ฐฉ์์ผ๋ก ํ์ฅํ ์ ์์ง๋ง, ์ฝ๋๊ฐ ์ง์ ๋ถํด์ง ์ ์๋ค. **extend()**๋ผ๋ ์ด๋ฆ์ ํจ์๋ก ๊ฐ์ฒด์ ์์ ์ด ์ํ๋ ๊ฐ์ฒด ํน์ ํจ์๋ฅผ ์ถ๊ฐ์ํจ๋ค.
__jQuery์ extend ํจ์
jQuery.extend = jQuery.fn.extend = function (obj: ์์, prop: ๋ถ๋ชจ) {
if (!prop) {
prop = obj; // ๋ถ๋ชจ๊ฐ ์์ผ๋ฉด ์์์ด ๋ถ๋ชจ
obj = this; // this๋ฅผ ์์์๊ฒ ํ ๋น
}
for (var i in prop) {
// deep copy
ob[i] = prop[i];
}
return obj;
};jQuery.fn์ jQuery์ ํ๋กํ ํ์- $.extend()๋
var elem = new jQuery(...); elem.extend()ํํ๋ก ํธ์ถ๊ฐ๋ฅ ob[i] = prop[i];์ ์์ ๋ณต์ฌ (shallow copy) => ์ฐธ์กฐ๊ฐ์ ๋ณต์ฌํ๋ ๊ฒฝ์ฐ ์ํฅ์ด ์๊ธด๋ค. ์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ๊น์ ๋ณต์ฌ๋ฅผ ํด์ผํจ.- ๊น์ ๋ณต์ฌ๋ฅผ ์ํด์ ๋น ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ extend ํจ์๋ฅผ ์ฌ๊ท์ ์ผ๋ก ํธ์ถ
// jQuery extend ํจ์ ์ค ์ผ๋ถ
...
for (; i < length; i++){
if( (options = arguments[i]) != null) {
/* ์ธ์๋ก ๋์ด์จ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ฅผ options๋ก ์ฐธ์กฐ์ํค๊ณ ,
๊ทธ ํ๋กํผํฐ๊ฐ null์ด ์๋ ๊ฒฝ์ฐ ๋ธ๋ก ์์ผ๋ก ์ง์
ํ๋ค. */
for (name in options){ // options๋ฅผ deep ์นดํผํ๋ค.
src = target[name]; // src๋ ๋ฐํ๋ ๋ณต์ฌ๋ณธ target์ ๊ฐ๋ฆฌํด
copy = options[name]; // copy๋ ๋ณต์ฌํ ์๋ณธ ํ๋กํผํฐ๋ฅผ ๊ฐ๋ฆฌํด
if (target === copy){ // ๋ฌดํ๋ฃจํ ๋ฐฉ์ง
continue; // continue๋ ๋ฃจํ์ ์คํ์ ์์ ํ ์ข
๋ฃํ์ง ์๊ณ for ๋ฃจํ์์๋ ์
๋ฐ์ดํธ ํํ์์ผ๋ก ์ ํํจ.
}
if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy))) ){
// deep ํ๋๊ทธ:boolean: extend์์ ์ธ์๋ก ๋ฐ์ : ๊น์ ๋ณต์ฌ๋ฅผ ํ ๊ฒ์ธ์ง ์ ํ ํ ์ ์๊ฒ ํ๋ค.
// copy: ์ฐธ์กฐํ์์ธ ๊ฒฝ์ฐ (๊ฐ์ฒด๋ ๋ฐฐ์ด์ธ ๊ฒฝ์ฐ) ๋ฌด์กฐ๊ฑด deep copy ์์
)
if ( copyIsArray ) {
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];
// ๋ฐฐ์ด ๋ณต์ฌ์ผ ๊ฒฝ์ฐ ๋น ๋ฐฐ์ด ์์ฑ
} else {
clone = src && jQuery.isPlainObject(src) ? src : {};
// ๊ฐ์ฒด ๋ณต์ฌ์ผ ๊ฒฝ์ฐ ๋น ๊ฐ์ฒด ์์ฑ
}
target[name] = jQuery.extend(deep, clone, copy); // ์ฌ๊ท..
} else if (copy !== undefined) {
target[name] = copy;
}
}
}
return target;
}const person = {
name: 'joy',
getName: function(){ return this.name; },
setName: function(arg){this.name = arg;}
}
function create_object(o) {
function F() {};
F.prototype = o;
return new F();
}
function extend(obj, prop) {
if(!prop) {prop = obj; obj = this;}
/* ์ธ์๊ฐ ํ๋๋ง ๋ค์ด์ค๋ ๊ฒฝ์ฐ,
prop ์ธ์์ obj๋ฅผ ํ ๋นํ๊ณ ,
ํ์ฌ๊ฐ์ฒด(this)์ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ฅผ ๋ณต์ฌํ๋ค.... */
for (let i in prop) obj[i] = prop[i]; // ์์ ๋ณต์ฌ์.
return obj;
}
const student = create_object(person);
const added = {
setAge: function(age){ this.age = age; }
getAge: function() {return this.age;}
}
extend(student, added); // 1
student.setAge(25);
console.log(student.getAge());- person๊ฐ์ฒด๋ฅผ ๊ฐ๊ณ ์๋ ํ๋กํ ํ์ ์ ๊ฐ๊ณ ์๋ student ์ธ์คํด์ค(์ปจํ ์คํธ)๊ฐ added๋ฅผ ์์๋ฐ๋๋ค. (deep copyํจ)
- student ์ธ์คํด์ค์๋ added ๊ฐ์ฒด๊ฐ ๋ณต์ฌ๋๋ค.
2-2. ํด๋์ค ๊ธฐ๋ฐ์ ์์
1๋ฒ์ ๊ฐ์ฒด์ ์์์ด์๊ณ , ์ง๊ธ์ ํด๋์ค์ ์ญํ ์ ํ๋ ํจ์๋ฅผ ์์ํ๋ ๊ฒ์ ์ค๋ช ํ๋ค. (์ปจํ ์คํธ ์์)
function Person(arg) { this.name = arg;}
Person.prototype.setName = function(value) { this.name = value; };
Person.prototype.getName = function() { return this.name; }
function Student(arg) {}
const you = new Person('JoyKim'); Student.prototype = you;
const me = new Student('NaYoung'); me.setName('Kim'); console.log(me.getName());
- you๋ Person์ ์ธ์คํด์ค (name: JoyKim)
- Student์ ํ๋กํ ํ์ ์ you๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
- me๋ Student์ ์ธ์คํด์ค
- Student์๋ ์ธ์๋ฅผ ๋ฐ์ name์ด ์์ผ๋ฏ๋ก โNaYoungโ์ ๋ฃ์ด์ค๋ ์๋ฌด๋ฐ ์ ์ฉ ์๋จ
- ์ด๋ฅผ ์ํด์ ์ธ์คํด์ค๊ฐ ์์ฑ๋ ๋ ๋ถ๋ชจํจ์๊ฐ ๋ฐ๋ก ์คํ๋ ์ ์๋๋ก Student์ ์คํ์ฝ๋๋ฅผ ๋ฃ๋๋ค.
function Student(arg){ Person.apply(this, arg) // ๋ถ๋ชจํจ์ Pseron์ ์คํํ๊ณ this๋ arg์ ๋ฐ์ธ๋ฉ! }
- me๊ฐ์ฒด์์ setName์ ํธ์ถํ๋ฉด ํ๋กํ ํ์ ์ฒด์ด๋์ ์ํด์ Person๊น์ง์ฌ๋ผ๊ฐ๋ค.
์ด ๋ก์ง์ ๋จ์ ์ me์ prototype์ด Student.prototype์ด๊ณ , ์ด๋ ๊ณณ you๋ฅผ ๊ฐ๋ฆฌํจ๋ค๋ ๊ฒ์ธ๋ฐ, ์ด๋ ๊ฒ ๋๋ฉด me๊ฐ you์ ์์ ๊ฐ๋ ์ด ๋๋ฉด์ ์๋ชป๋ ์ค๊ณ๊ฐ ๋๋ค.
me์ you์ ๋ ๋ฆฝ์ฑ์ ์ํด์ ์ค๊ฐ ์ญํ ์ ํด์ฃผ๋ ํ๋กํ ์ฝ ๋น ํจ์ F()๋ฅผ ์ถ๊ฐํ๋ค.
function Person(arg) { this.name = arg;}
Function.prototype.method = function(name, func) { this.prototype[name] = func };
Person.method('setName', function(value) { this.name = value; };)
Person.method('getName', function() { return this.name; })
function Student(arg) {}
function F(){};
F.prototype = Person.prototype;
Student.prototype = new F();
Student.prototype.constructor = Student;
Student.super = Person.prototype;
const me = new Student('NaYoung');
const you = new Person('YoungRan');
me.setName('Kim');- Function ํ๋กํ ํ์ ์ ํ๋กํ ํ์ ํจ์๋ฅผ ๋ง๋ค์ด์ฃผ๋, ์ฌ์ฌ์ฉํ ์ ์๋ method๋ผ๋ ๋ฉ์๋๋ฅผ ์ถ๊ฐํ๋ค. (์์ค ๋ค์ด๋ฐ ์์ ํท๊ฐ)
- F์ ํ๋กํ ํ์ ์ Person์ ํ๋กํ ํ์ ์ ์ฐธ์กฐํ๊ฒ ํจ์ผ๋ก์จ ์ค๊ฐ์ญํ ์ ํ๊ฒํจ
- ๊ทธ ์ค๊ฐ์ญํ ์ ํ๋ F์ ์ธ์คํด์ค๋ฅผ Student์ ํ๋กํ ํ์ ์ด ์ฐธ์กฐํ๋๋ก ํจ. (ํ์ฌ Student => F => Person)
- ํ๋กํ ํ์ ์ฒด์ธ์ ์ํด์ Student ํ๋กํ ํ์ ์ ์์ฑ์๋ฅผ Student๋ก ํ ๋น.
- Student๊ฐ Person.prototype์๋ ์ ๊ทผํ๊ธฐ ์ํด์ super๋ผ๋ ๋ฉ์๋ ์์ฑ
me๋ Person์ ์์๋ฐ์ Student์ ์ธ์คํด์ค์ด๊ณ you๋ Person์ ์ธ์คํด์ค.
์ ๋ก์ง์ ๋ชจ๋ํ ์ํค๋ฉด..(by.์คํ ์ ์คํ ํ๋ ธํ[JavaScript Pattersn])
const inherit = function (Parent, Child) {
const F = function () {};
return function (Paretn, Child) {
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.super = Parent.prototype;
};
};ํด๋ก์ ๋ F()ํจ์๋ฅผ ์ง์์ ์ผ๋ก ์ฐธ์กฐํ๋ค. F()๋ ๊ฐ๋น์ง ์ปฌ๋ ์ ์ ๋์์ด ๋์ง ์๊ณ ๊ณ์ ๋จ์ ์๋ค. ์ด๋ฅผ ์ด์ฉํด ํจ์ F()์ ์์ฑ์ ๋จ ํ ๋ฒ ์ด๋ฃจ์ด์ง๊ณ inheritํจ์๊ฐ ๊ณ์ํด์ ํธ์ถ๋์ด๋ ํจ์ F()์ ์์ฑ์ ์๋ก ํ ํ์๊ฐ ์๋ค.
3. ์บก์ํ (feat. ํด๋ก์ ) - ์ ๋ณด ๊ณต๊ฐ์ ์ฌ๋ถ. ์ ๋ณด ์๋ ๊ฐ๋
(Typescript์์๋ public,
private, protected ๋ฉค๋ฒ๋ฅผ ์ ์ธํจ์ผ๋ก์จ ํด๋น ์ ๋ณด๋ฅผ ์ธ๋ถ๋ก ๋
ธ์ถ์ํฌ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ) - ์๋ฐ์คํฌ๋ฆฝํธ
es6์์๋ get, set ํค์๋๋ก ์ธ๋ถ์์ ํด๋น ํด๋์ค ํน์ ํจ์ ๋ด๋ถ์ ์ ๊ทผ ํ ์ ์๋ค. (get์ readonly)
const Person = function (arg) {
let name = arg ? arg : 'joy';
this.getName = function () {
return name;
};
this.setName = function (arg) {
name = arg;
};
};
const me = new Person();
console.log(me.getName());
me.setName('NaYoung');
console.log(me.getName());
console.log(me.name);- Person์ ๋ด๋ถ public ํจ์๋ค์ **ํด๋ก์ **์ญํ ์ ํ๋ฉด์ name์ ์ ๊ทผํ๊ณ ์๋ค.
// ๋ชจ๋ํจํด
const Person = function(arg){
const name = arg? arg: 'joy';
// name์ private ๋ฉค๋ฒ
return {
getName: function() { return name;},
setName: fucntion(arg){ name = arg;}
}
}
const me = Person()
console.log(me.getName())- ์ ๊ทผํ๋ private ๋ฉค๋ฒ๊ฐ ๊ฐ์ฒด๋ ๋ฐฐ์ด์ด๋ฉด(๋ ํผ๋ฐ์ค) ์์ ๋ณต์ฌ๋ก ์ฐธ์กฐ๋ง์ ๋ฐํํ๋ฏ๋ก ์ฌ์ฉ์๊ฐ ์ดํ ์ด๋ฅผ ์ฝ๊ฒ ๋ณ๊ฒฝํ ์ ์๋ค. (Deep copy, Shallow copy)
- ๊ฐ์ฒด๋ง์ ๋ฐํํ๊ธฐ ๋๋ฌธ์ Person ํจ์์ ํ๋กํ ํ์
์ ์ ๊ทผํ ์ ์๋ค.
const Person3 = (function (arg) { const name = arg ? arg : 'joy'; var Func = function () {}; Func.prototype = { getName: function () { return name; }, setName: function (arg) { name = arg; }, }; return Func; })();
4. ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ ์์ฉ ์์
ํจ์์ ํ๋กํ ํ์ ์ฒด์ธ extend ํจ์ ์ธ์คํด์ค๋ฅผ ์์ฑํ ๋ ์์ฑ์ ํธ์ถ์ ์ด์ฉํด์ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ํด๋์ค ๊ธฐ๋ฅ์ ํ๋ ํจ์ ๋ง๋ค๊ธฐ
4-1-1. subClass ํจ์ ๊ตฌ์กฐ
subClassํจ์๋ ๋ณ์ ๋ฐ ๋ฉ์๋๊ฐ ๋ด๊ธด ๊ฐ์ฒด๋ฅผ ์ธ์๋ก ๋ฐ์ ๋ถ๋ชจ ํจ์๋ฅผ ์์๋ฐ๋ ์์ ํด๋์ค๋ฅผ ๋ง๋ ๋ค.
๋ถ๋ชจํจ์๋ subClass() ํจ์๋ฅผ ํธ์ถํ ๋ this ๊ฐ์ฒด๋ฅผ ์๋ฏธํ๋ค.
const SuperClass = subClass(obj); // ์์๋ฐ์ ํด๋์ค
const SubClass = SuperClass.subClass(obj); // SubClass๋ SuperClass๋ฅผ ์์๋ฐ๋๋ค.์ด์ฒ๋ผ SuperClass๋ฅผ ์์๋ฐ๋ subClass๋ฅผ ๋ง๋ค๊ณ ์ ํ ๋, SuperClass.subClass()์ ํ์์ผ๋ก ํธ์ถํ๊ฒ ๊ตฌํํ๋ค. ์ฐธ๊ณ ๋ก ์ต์์ ํด๋์ค์ธ SuperClass๋ ์๋ฐ์คํฌ๋ฆฝํธ์ Fucntion์ ์์๋ฐ๊ฒ ํ๋ค.
function subClass(obj) {
/*
1. ์์ ํด๋์ค (ํจ์๊ฐ์ฒด) ์์ฑ
2. ์์ฑ์ ํธ์ถ (ํด๋์ค ํจ์๋ฅผ ์์ฑํ๊ธฐ ์ํด์)
3. ํ๋กํ ํ์
์ฒด์ธ์ ํ์ฉํ ์์ ๊ตฌํ
4. obj๋ฅผ ํตํด ๋ค์ด์จ ๋ณ์ ๋ฐ ๋ฉ์๋๋ฅผ ์์ ํด๋์ค์ ์ถ๊ฐ
5. ์์ ํจ์ ๊ฐ์ฒด ๋ฐํ
*/
}4-1-2. ์์ ํด๋์ค ์์ฑ ๋ฐ ์์
function subClass(obj) {
...
const parent = this; // ๋ถ๋ชจํด๋์ค๋ฅผ ๊ฐ๋ฆฌํค๋ parent๋ this๋ฅผ ๊ทธ๋๋ก ์ฐธ์กฐ
const F = function(){}; // ์ค๊ฐ์ญํ
const child = function(){}; // ์์๊ฐ์ฒด
F.prototype = parent.prototype;
child.prototype = new F(); // ๋ถ๋ชจ์ ํ๋กํ ํ์
์ ์ฐธ์กฐํ๋ ํ๋กํ ํ์
์ ๊ฐ๊ณ ์๋ F๋ก๋ถํฐ ๋ง๋ค์ด์ง ์์ฑ์ ํจ์๋ฅผ child ํ๋กํ ํ์
์ด ์ฐธ์กฐํ๋๋กํ๋ค.ใ
child.prototype.constructor = child;
child.parent = parent.prototype;
child.parent_constructor = parent;
...
return child;
}์์ ํด๋์ค๋ child ๋ผ๋ ์ด๋ฆ์ ํจ์ ๊ฐ์ฒด๋ฅผ ์์ฑํจ์ผ๋ก์จ ๋ง๋ค์ด์ก๋ค.
4-1-3. ์์ ํด๋์ค ํ์ฅ
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
child.prototype[i] = obj[i];
}
}hasOwnProperty ์ธ์๋ก ๋๊ธฐ๋ ์ด๋ฆ์ ํด๋นํ๋ ํ๋กํผํฐ๊ฐ ๊ฐ์ฒด ๋ด์ ์๋์ง๋ฅผ ํ๋ค.
ํ๋กํ ํ์ ์ฒด์ธ์ ํ๊ณ ์ฌ๋ผ๊ฐ์ง ์๊ณ ํด๋น๊ฐ์ฒด ๋ด์์๋ง ์ฐพ๋๋ค๋ ๊ฒ์ ์ ์
o = new Object();
o.prop = 'exists';
o.hasOwnProperty('prop'); // true
o.hasOwnProperty('toString'); // false
o.hasOwnProperty('hasOwnProperty'); // false4-1-4. ์์ฑ์ ํธ์ถ
ํด๋์ค์ ์ธ์คํด์ค๊ฐ ์์ฑ๋ ๋, ํด๋์ค ๋ด์ ์ ์๋ ์์ฑ์๊ฐ ํธ์ถ๋ผ์ผํ๋ค. ๋ถ๋ชจ ํด๋์ค์ ์์ฑ์ ์ญ์ ํธ์ถ๋์ด์ผํ๋ค. (์ด๊ธฐํ๋ฅผ ์ํด์)
const child = function () {
if (parent.hasOwnProperty('_init')) {
parent._init.apply(this, arguments);
}
if (child.prototype.hasOwnProperty('_init')) {
child.prototype._init.apply(this, arguments);
}
};const SuperClass = subClass();
const SubClass = SuperClass.subClass();
const Sub_SubClass = SubClass.subClass();
const instance = new Sub_SubClass();instance ์์ฑ์ SuperClass ์์ฑ์๊ฐ ํธ์ถ๋์ง ์๋๋ค. => ๋ถ๋ชจํด๋์ค์ ์์ฑ์๋ฅผ ํธ์ถํ๋ ์ฝ๋๋ฅผ ์ฌ๊ท์ ์ผ๋ก ๊ตฌํํ์ฌ ํด๊ฒฐํ๋ค.
const child = function () {
const _parent = child.parent_constructor;
if (_parent && _parent !== Function) {
_parent.apply(this, arguments);
}
if (child.prototype.hasOwnProperty('_init')) {
child.prototype._init.apply(this, arguments);
}
};- ํ์ฌ ํด๋์ค์ ๋ถ๋ชจ ์์ฑ์๊ฐ ์์ผ๋ฉด, ๊ทธ ํจ์๋ฅผ ํธ์ถํ๋ค. ๋ค๋ง ๋ถ๋ชจ๊ฐ Function์ด ๊ฒฝ์ฐ๋ ์ต์์ ํด๋์ค์ ๋๋ฌํ์ผ๋ฏ๋ก ์คํํ์ง ์๋๋ค.
์ต์ข
function subClass(obj){
/*
1. ์์ ํด๋์ค (ํจ์๊ฐ์ฒด) ์์ฑ
2. ์์ฑ์ ํธ์ถ (ํด๋์ค ํจ์๋ฅผ ์์ฑํ๊ธฐ ์ํด์)
3. ํ๋กํ ํ์
์ฒด์ธ์ ํ์ฉํ ์์ ๊ตฌํ
4. obj๋ฅผ ํตํด ๋ค์ด์จ ๋ณ์ ๋ฐ ๋ฉ์๋๋ฅผ ์์ ํด๋์ค์ ์ถ๊ฐ
5. ์์ ํจ์ ๊ฐ์ฒด ๋ฐํ
*/
const parent = this === window ? Function : this;
const F = function(){}
const child = function() {
const _parent = child.parent;
if(_parent && _parent !== Function){
parent.apply(this, arguments);
}
if(child.prototype._init)){
child.prototype._init.apply(this, arguments);
}
}
F.prototype = parent.prototype;
child.prototype = new F();
child.prototype.constructor = child;
child.parent = parent;
child.subClass = arguments.callee;
for (let i in obj){
if (obj.hasOwnProperty(i)){
child.prototype[i] = obj[i];
}
}
return child
}By Joy.
- ๋ด๋ถํจ์๋ฅผ ์ ์ธํ ๋์ this๋ก ๋ฐ์ธ๋ฉ๋ ํจ์๋ฅผ ์ ์ธํ๋ ๊ฒ์ ์ฐจ์ด์ ? ๊ธฐ์ค?
- ํ๋กํ ํ์ ์ฒด์ด๋์ ๋ง๋ ์ด์ ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ์ง์ํ๊ธฐ ์ํด ๋ถ๋ชจ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋ ์ฐธ์กฐ๋งํฌ ํํ๋ก ์จ๊ฒจ์ง ํ๋กํผํฐ.
- (Naming) ๋ณต์ฌ์ ๋ณต์ฌํ ๋์์ copy, ๋ณต์ฌ์ ๊ฒฐ๊ณผ๋ฌผ์ clone
- shallow copy์ ๋ค๋ฅด๊ฒ deep copy๋ ์ฌ๊ท์ ์ผ๋ก ํธ์ถํด์ผํจ. (๋ค์ ์ ๋ฆฌ)