반응형

var obj = {};

// var obj = new Object() 이다.

// Object 도 기본적으로 함수이다. function Object()


// var o = new obj();

// 이렇게는 사용할 수 없다. obj is not constructor.

// constructor 가 있어야만 new 를 통해서 객체를 만들수 있다.

// 따라서 함수만 new 키워드를 사용 할 수 있다.


var a = {a: 1};

// a ---> Object.prototype ---> null


// Error literal object 에는 prototype 을 재정의 할 수 없음.

//a.prototype.getA = function() {

//    return this.a;

//}


// b 의 prototype 이 a 가 된다.

var b = Object.create(a);

// b ---> a ---> Object.prototype ---> null

//console.log(b.a); // 1 (상속됨)


// Error literal object 에는 prototype 을 재정의 할 수 없음.

//b.prototype.getA = function() {

//    return "A";

//}



// 일반 객체에는 prototype 을 정의할 수 없다.

// 그냥 prototype 이라는 속성으로 인식함.

try {

    var p = {

        a: 10,

        b: 20

    }


    // 일반객체에 prototype 을 정의할 수 없음.

    // "prototype" 이라는 속성이 추가 되는 것임.

    // __proto__ 변수에 매핑 되는 것이 아님.

    p.prototype = {

        getA: function () {

            return this.a;

        }

    }


    console.log("p = ", p);

    console.log("p.a = ", p.a);

    console.log("p.__proto__ = ", p.__proto__);

    console.log("p.prototype = ", p.prototype);

    //console.log("p.getA() = ", p.getA()); // p 객체에는 getA 함수가 없음. 프로토타입 체인으로도 찾을 수 없음.

    //console.log("p.prototype.getA() = ", p.prototype.getA()); // p.prototype.getA 함수에서 this 지시자를 사용 할 수 없음.



    // Object.create(p) 이용하여 p1 이라는 새로운 객체 생성.

    // p1.__proto__ = p 이라는 의미가 됨.

    console.log();

    console.log("=================================================");

    console.log("p1 = Object.create(p)");

    var p1 = Object.create(p);


    console.log("p1 = ", p1);

    console.log("p1.__proto__ = ", p1.__proto__);

    console.log("p1.prototype = ", p1.prototype); // "prototype" 이라는 속성.

    console.log("p1.__proto__.__proto__ = ", p1.__proto__.__proto__);


    console.log("p1.a = ", p1.a); // p1.__proto__.a

    //console.log("p1.getA() = ", p1.getA()); // p1, p1__proto__ 객체에 getA 라는 함수는 없다.

    //console.log("p1.prototype.getA() = ", p1.prototype.getA()); // p1__proto__.prototype.getA 함수에서 this 지시자를 사용 할 수 없음.


} catch(err) {

    console.log(err);

}


// prototype 설명 : https://medium.com/@bluesh55/javascript-prototype-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-f8e67c286b67.

// 함수를 정의하는 순간 Prototype Object 도 생성됨.

// Prototype Object 는 일반적인 객체와 같으며 기본적인 속성으로 constructor 와 __proto__ 를 가지고 있음.

// constructor는 Prototype Object와 같이 생성되었던 함수.

// __proto__는 Prototype Link.

// __proto__는 객체가 생성될 때 조상이었던 함수의 Prototype Object를 가리킴.

// Foo 는 function 객체.

// Foo.__proto__ == Function.prototype. 따라서, F.call() 호출 가능하다.

// Foo.constructor 는 Function. Foo.__proto__ 의 생성자.

function Foo() {

    this.a = 1;

}



// new 키워드로 객체 생성. 생성자 함수 호출. 생성자를 바탕으로 객체를 생성한다.

// foo.__proto__ 은 Foo.prototype 이다.

// foo.__proto__.constructor 는 function Foo() 이다.

// foo.hasOwnProperty("constructor") === false

var foo = new Foo();

console.log("foo.a", foo.a);

// var foo = new Object();

// foo.__proto__ = Foo.prototype;

// Foo.call(foo);



// prototype과 constructor는 부모자식 관계

if(foo.__proto__ === Foo.prototype) {

    console.log("foo.__proto__ === Foo.prototype");

}


if(foo.__proto__.constructor === Foo) {

    console.log("foo.__proto__.constructor === Foo");

}




function Person() {

    this.name = "anonymous";

    this.job = "none";

    this.sayHello = function () {

        console.log("Hello, my name is " + this.name);

    };

}


function Unikys() {

    this.name = "Unikys";

    this.job = "Programmer";

}


// #1.

Unikys.prototype = new Person();

var unikys1 = new Unikys();

unikys1.sayHello();

//unikys1 instanceof Unikys === true, unikys1 의 prototype 과 Unikys 의 prototype 이 같기 때문.

//unikys1 instanceof Person === true

// unikys1.constructor = function Persion()

// constructor 는 객체에 있는 것이 아니라 prototype 에 있는 것. prototype 의 생성자.(Person객체의 생성자 = function Persion()).

// constructor 가 있는 prototype 을 다른 새로운 객체로 덮어씌우게 되면 원래 자기 자신의 contstructor 는 상실하게 됨.

// 따라서 unikys1 이 new Unikys()로 생성했다고 하더라도 constructor 는 Unikys() 가 아니라 prototype 으로 덮어씌운 객체의 constructor 인 Person() 이 된다.



// #2.

var unikys2 = Object.create(Person.prototype);

unikys2.name = "Unikys";

// 부모 함수의 일부 메서드에 위임을하고 새 개체를 만들지 않으려면 Object.create 를 사용하는 것이 좋음.

// 부모 함수에 있는 속성은 사용할 수 없기 때문에 부모 속성을 사용하지 않는 경우에 사용.

// unikys2.sayHello(); // Error.

// unikys2 의 prototype 을 Person.prototype 으로 정의. unikys2.__proto__ === Person.prototype.

// 대신 Person 의 속성들은 사용할 수 없어서 추가로 정의해야 함.(name 등)

// unikys2 instanceof Person === true

// unikys2.constructor === Person. true.



// #3.

var unikys3 = Object.create(Person);

unikys3.name = "Unikys";

//unikys3.sayHello();

// unikys3 의 prototype 을 Person 으로 정의. unikys3.__proto__ === Person

// unikys3.constructor === Person. false.

// unikys3.constructor === Function. true.

// constructor 는 prototype 의 생성자를 가르킨다.

// unikys3 instanceof Person === false

// unikys3 instanceof Function === true

// Person.isPrototypeOf(unikys3) == true




// prototype은 모든 객체가 공유하고 있어서 한 번만 만들어지지만, this에 넣은 것은 객체 하나를 만들 때마다 메소드도 하나씩 만들어지기 때문에 불필요한 메모리 낭비.

Person.prototype.yell = function () {

    console.log("My name is " + this.name);

}


// #4.

// prototype chain 추가.

Unikys.prototype = Object.create(Person.prototype); // Unikys.prototype = Person.prototype; 으로 했을 경우에는 Unikys.prototype 에 속성을 추가하면 Person.prototype 에도 추가가 된다.

// Unikys.prototype.__proto__ === Person.prototype

// Unikys.prototype.constructor === Person

// Unikys.constructor === Function


console.log(Unikys.constructor);

Unikys.prototype.constructor = Unikys;

// Unikys 객체들의 constructor 를 Unikys 로 정의.


var unikys4 = new Unikys();

console.log(unikys4.name);

//unikys4.sayHello();

// unikys4.__proto === Unikys.prototype

// unikys4.constructor === Unikys

// unikys4.hasOwnProperty("constructor") === false

// unikys4.__proto__.hasOwnProperty("constructor") === false

// unikys4.__proto__.hasOwnProperty("yell") === false

// unikys4.__proto__.__proto__.hasOwnProperty("yell") === true



function Vehicle(name, speed) {

    this.name = name;

    this.speed = speed;

}

Vehicle.prototype.drive = function () {

    console.log(this.name + ' runs at ' + this.speed)

};


function Sedan(name, speed, maxSpeed) {

    // Vehicle 생성자에 this와 arguments를 적용하라.

    // Sedan은 매개변수로 name과 speed, maxSpeed. maxSpeed는 Vehicle이 갖고 있지 않기 때문에 무시. maxSpeed 속성을 따로 추가.

    Vehicle.apply(this, arguments)

    this.maxSpeed = maxSpeed;

}


// Sedan.prototype = new Vehicle(); // 이렇게 하면 new Sedan 할때 Vehicle 이 두번 호출 되는 결과가 발생한다. 그리고 Vehicle 의 속성까지도 가지게 된다.

Sedan.prototype = Object.create(Vehicle.prototype);

Sedan.prototype.constructor = Sedan;

Sedan.prototype.boost = function () {

    console.log(this.name + ' boosts its speed at ' + this.maxSpeed);

};

var sonata = new Sedan('sonata', 100, 200);

sonata.drive(); // 'sonata runs at 100'

sonata.boost(); // 'sonata boosts its speed at 200'



printOwnProperties(sonata);



function printOwnProperties(obj) {

    console.log('==============================================');

    console.log('============ Print Own Properties ============');

    console.log('==============================================');

    for (var key in obj) {

        console.log('property       = ' + key);

        console.log('typeof         = ' + (typeof key));

        console.log('hasOwnProperty = ' + (obj.hasOwnProperty(key)));

        console.log('value          = ' + obj[key]);

        console.log('');

    }

}


var c = function() {return a;}



반응형

'프로그래밍 > Javascript' 카테고리의 다른 글

undefined ?  (0) 2021.08.06
javascript containsAll  (1) 2016.11.04
[jquery] hide, show 함수, visibility 속성  (0) 2016.10.28
jquery crossdomain ajax jsonp  (1) 2015.10.30
한글, 영문 check  (0) 2011.12.27

+ Recent posts