1,建構函式建立物件造成的記憶體浪費,和原型的引入

 function Person(name,age){
        this.name = name;
        this.age = age;
        this.introduce = function(){
            alert('我是'+this.name)
        };
    }



    var  p1 = new Person('小敏',12);

    var  p2 = new Person('小敏',12);
    var  p3 = new Person('小敏',12);
//.....................

如上不斷地例項化Person物件,每次例項化都要為intrduce方法開闢新的記憶體空間,這樣做浪費了記憶體空間

下面想了一個辦法,在外部為方法寫一個函式,讓物件中的方法指向這個函式,當物件呼叫方法時,通過屬性指向方法函式所在的地址,

那麼就可以實現多個物件公用一個方法函式

 function introduce(){
        alert('我是'+this.name);
    }
    // var introduce = '你好';  //缺點當其他人定義變數與函式名相同時,會報錯
    function Person(name,age){
        this.name = name;
        this.age = age;
        this.introduce = introduce;
    }
    //例項化物件
    var  p1 = new Person('小敏',12);
    var  p2 = new Person('小明',12);
    p1.introduce(); //第5行有效 則 這裡會報錯

    // console.log(p1.introduce == p2.introduce); //true

上面的程式碼依然存在缺陷,封裝物件後,假如其他人看不到原始碼的情況下,且定義了一個與方法函式名相同的變數,那麼這個程式將會報錯,程式不能正常執行.

下面我們引入原型,prototype

原型存在於每個函式物件中,是函式物件的屬性    函式名.prototype.方法名 = function(){函式體}    (當然我們也可以通過這種方式為建構函式新增屬性)

 function Person(name,age){
        this.name = name;
        this.age = age;
    }
    Person.prototype.introduce = function(){//prototype  原型,模式
        alert('我是'+this.name);
    };

    //例項化物件
    var  p1 = new Person('小敏',12);
    var  p2 = new Person('小明',12);
    p1.introduce();

    console.log(p1.introduce == p2.introduce); //true

3,建構函式  原型  例項化物件   之間的關係

建構函式中存在一個屬性叫  prototype  也就是原型,原型本身又是一個物件,它內部儲存著  constructor 構造器,還用使用者定義的需要共享的屬性以及方法

prototype 原型物件中的constructor屬性 指向的是prototype自己所在的建構函式

在例項化物件中存在著一個叫 __proto__的屬性,同時它本身是一個物件,確切地說  它指向建構函式中的 prototype物件所在的記憶體空間,所以  __proto__ ==Prototype ,

但是__proto__是一個非標準化的物件,  它內部的方法 可以直接 被它的父級物件直接呼叫,  如上段程式碼中  introduce方法在 __proto__物件中, __proto__是p1的屬性, 正常呼叫方式是  p1.__proto__.introduce(),   由於__proto__的非標準化, p1.introduce()  呼叫方法也是行得通的.