Recent Posts
Recent Comments
Link
11-21 14:38
Today
Total
관리 메뉴

삶 가운데 남긴 기록 AACII.TISTORY.COM

javascript prototype 본문

DEV&OPS/Javascript

javascript prototype

ALEPH.GEM 2022. 2. 23. 17:46

생성자 안에 메서드를 정의할 때의 문제점

생성자로 객체를 생성 할 때마다 똑같은 함수가 생성되어 메모리를 소비하게 됩니다.

이런 문제는 프로토 타입 객체에 메서드를 정의하는 방식으로 해결합니다.

 

프로토 타입 객체

함수의 prototype 프로퍼티가 가리키는 객체를 그 함수의 프로토 타입 객체라고 합니다.

기본적으로 빈 객체를 가리킵니다.

프로토타입 객체의 프로퍼티는 생성자로 생성한 모든 인스턴스에서 그 인스턴스의 프로퍼티처럼 사용할 수 있습니다.

function F(){};
F.prototype.prop = "prototype value";
var obj = new F();
console.log(obj.prop);		//prototype value;
//프로토 타입 객체의 프로퍼티는 읽기만 하고 수정이 불가능합니다.
obj.prop = "instance value";
console.log(obj.prop);				//instance value
console.log(F.prototype.prop);		//prototype value

프로토 타입 객체를 생성된 인스턴스가 상속하고 있는 것입니다.

프로토 타입으로 메서드를 정의하면 인스턴스가 생성될 때마다 메서드도 같이 생성되는 것을 피할 수 있습니다.

function Circle(center, radius){
    this.center = center;
    this.radius = radius;
}
//생성자의 프로토 타입 프로퍼티에 area 메서드를 추가
Circle.prototype.area = function(){
    return Math.PI*this.radius*this.radius;
}

var c1 = new Circle({x:0, y:0}, 2.0);
console.log("원 넓이:" + c1.area());

 

프로토 타입 체인

__proto__ 프로퍼티는 해당 객체에 상속을 해준 부모 객체를 가리킵니다.

그래서 부모 객체의 프로퍼티를 사용할 수 있습니다.

객체의 프로토타입은 Object.getPrototypeOf 메서드로도 가져올 수 있습니다.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title> </title>
    <script>
        var ObjA = {
            name: "Tom",
            sayHello: function(){console.log("Hello! " + this.name);}
        };
        var ObjB = {
            name: "Ann"
        };
        ObjB.__proto__ = ObjA;
        var ObjC = {};
        ObjC.__proto__ = ObjB;
        console.log(Object.getPrototypeOf(ObjC));   /* {name: 'Ann'} */
        ObjC.sayHello();		/* "Hello! Ann" */
    </script>
</head>
<body>

</body>
</html>

 

프로토 타입 객체의 프로퍼티

constructor 
생성자의 프로토타입 프로퍼티는 프로토타입 객체를 참조하며, 이 포로토타입 객체의 constructor 프로퍼티가 생성자를 참조합니다.
function F(){};
obj = new F();
console.log(obj.constructor);       //Function F(){}
프로토 타입 객체의 교체
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title> </title>
    <script>
        /* 생성자 Circle 함수 */
        function Circle(center, radius){
            this.center = center;
            this.radius = radius;
        }
        Circle.prototype = {
            constructor: Circle,    /* 생성자를 constructor로 */
            area: function(){return Math.PI*this.radius*this.radius;}
        };
        var c = new Circle({x:0, y:0}, 2.0);
        /* 생성자 Circle으로 생성된 인스턴스들(c)은 프로토 타입 객체의 property를 사용할수 있습니다.*/ 
        console.log(c.constructor);             /* Function Circle */
        console.log(c.area());                  /* 12.566370614359172 */
        console.log(c instanceof Circle);       
    </script>
</head>
<body>

</body>
</html>

여기서 instanceof는 c가 Circle의 인스턴스이면 true 아니면 false를 리턴하는 연산자입니다.

 

인스턴스 생성 후에 생성자의 프로토 타입을 수정한 경우
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title> </title>
    <script>
        /* 생성자 Circle 함수 */
        function Circle(center, radius){
            this.center = center;
            this.radius = radius;
        }
        var c = new Circle({x:0, y:0}, 2.0);
        /* 인스턴스(c)를 생성한 후에 생성자의 프로토 타입을 수정하면 상속 관계가 끊어집니다. */
        Circle.prototype = {
            constructor: Circle,    /* 생성자를 constructor로 */
            area: function(){return Math.PI*this.radius*this.radius;}
        };
        console.log(c.constructor);             /* Function Circle */
        console.log(c instanceof Circle);       /* false */
        console.log(c.area());                  /* 상속을 할 수 없으므로 에러가 나옴 */
    </script>
</head>
<body>

</body>
</html>

생성자가 기존에 가지고 있던 프로토 타입 객체에 프로퍼티를 추가한 경우 상속이 가능합니다.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title> </title>
    <script>
        //생성자 Circle 함수
        function Circle(center, radius){
            this.center = center;
            this.radius = radius;
        }
        var c = new Circle({x:0, y:0}, 2.0);
        Circle.prototype.area = function(){return Math.PI*this.radius*this.radius; };
        console.log(c.constructor);             /* Function Circle */
        console.log(c instanceof Circle);       /* true */
        console.log(c.area());                  /* 12.566370614359172 */
    </script>
</head>
<body>

</body>
</html>

isPrototypeOf 메서드

프로토타입객체.isPrototypeOf(객체)

특정 객체가 다른 객체의 프로토 타입 체인에 포함되어 있으면 true, 없으면 false를 리턴합니다.

        function F(){};
        var obj = new F();
        console.log(F.prototype.isPrototypeOf(obj));            //true
        console.log(Object.prototype.isPrototypeOf(obj));       //true
        console.log(Date.prototype.isPrototypeOf(obj));         //false

 

Object.prototype

Object.prototype 프로퍼티의 메서드는 모든 인스턴스에서 사용할 수 있습니다.

모든 인스턴스들의 프로토 타입 체인의 최상위이기 때문입니다.

Object.prototype의 메서드들
hasOwnProperty(key) 호출한 객체가 key 이름으로 된 프로퍼티를 소유하는지 여부(boolean)
isPrototypeOf(obj) 호출한 객체가 인수 obj에 지정한 프로토 타입인지 여부(boolean)
toString() 호출한 객체를 문자열로 리턴
valueOf() 호출한 객체의 원시 값을 리턴
                   

var day = new Date(); 하면

인스턴스 day의 프로토 타입은 Date.prototype 이므로 Date.prototype의 프로퍼티와 메서드를 상속받습니다.

Date.prototype의 프로토타입은 Object.prototype입니다.

따라서 인스턴스 day에서 Object.prototype의 메서드와 프로퍼티를 상속받아 사용할 수있습니다.

이렇게 프로토 타입 체인으로 연결되어있습니다. 

 

 

Object.create

명시적으로 프로토타입을 지정해서 객체를 생성할 수 있습니다. 

직관적으로 상속을 표현할 수 있습니다.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title> object create</title>
    <script>
        var person1 = {
            name: "Tom",
            sayHello: function(){
                console.log("Hello! "+this.name);
            }
        }
        /* Object.create(생성할객체의 프로토타입, 생성할객체의 프로퍼티) */
        var person2 = Object.create(person1);
        person2.name = "Huck";
        person2.sayHello();     /* Hello! Huck */
        person1.sayHello();     /* Hello! Tom */
        /* person2의 프로토타입 */
        console.log(person2.__proto__);     /* {name: 'Tom', sayHello: f} */
    </script>
</head>
<body>

</body>
</html>

 

Object.create(null);  null로 생성하면 프로토 타입이 없는 객체를 생성합니다.

빈 객체를 생성하려면

var obj = Object.create(Object.prototype); 

으로 할 수도 있습니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90

'DEV&OPS > Javascript' 카테고리의 다른 글

JSON  (0) 2022.03.02
javascript object property  (0) 2022.03.02
javascript ECMAScript 6부터 추가된 함수와 객체의 기능  (0) 2022.02.21
javascript 함수2  (0) 2022.02.21
javascript 함수  (0) 2022.02.21