在講原型之前先補點知識。。。。
構(gòu)造函數(shù)的注意事項
- 默認(rèn)函數(shù)首字母大寫。
- 構(gòu)造函數(shù)并沒有顯示返回任何東西,當(dāng)調(diào)用構(gòu)造函數(shù)時,new會自動創(chuàng)建this對象,且類型就是構(gòu)造函數(shù)類型。
- 因為構(gòu)造函數(shù)也是函數(shù),所以可以直接調(diào)用,但是它的返回值是undefine,此時構(gòu)造函數(shù)里面的this對象等于全局this對象。
原型
- 構(gòu)造函數(shù)中有一個屬性:
prototype,叫原型,是給我們程序員用的。 - 實例對象中有一個屬性:
__proto__,也叫原型,這個是給瀏覽器看的。 - 構(gòu)造函數(shù)中的原型和實例對象中的原型都是屬性,也都是對象。
- 構(gòu)造函數(shù)中的
prototype和實例中的__proto__指向相同。 -
prototype的數(shù)據(jù)可以被實例對象訪問和使用。 - 如果希望數(shù)據(jù)能夠共享,應(yīng)該把數(shù)據(jù)放在原型中寫屬性和方法,如果不需要共享,那就放在構(gòu)造函數(shù)中定義。
- 實例對象調(diào)用的方法,如果在構(gòu)造函數(shù)的
prototype中存在就可以直接被調(diào)用
例子:
//構(gòu)造函數(shù)
function Person(name, age) {
this.name = name;
this.age = age;
this.eat = function () {
console.log("今天晚上我要吃雞腿");
};
}
//實例對象
var p = new Person("小黑", 12);
console.dir(p.__proto__);
console.dir(Person.prototype);
console.dir(p);
console.dir(Person);
/*
*
* 構(gòu)造函數(shù)中都有一個屬性:prototype,叫原型,是程序員用的
* 實例對象中都有一個屬性:`__proto__`,叫原型,是瀏覽器用的,不標(biāo)準(zhǔn)
* 無論是`prototype`還是`__proto__`都可以看成是一個對象
*
* 構(gòu)造函數(shù)中的原型(prototype)和實例對象中的原型`__proto__`都是屬性,也都是對象
* 構(gòu)造函數(shù)中的prototype和實例對象中的`__proto__`指向相同
* */
//構(gòu)造函數(shù)中只有屬性
function Person(name, age) {
this.name = name;
this.age = age;
}
//在Person的原型中添加eat方法
Person.prototype.eat = function () {
console.log("有了");
};
var p1 = new Person("小黑", 20);
var p2 = new Person("小白", 21);
//實例對象是可以使用的
p1.eat();
p2.eat();
console.dir(p1);
console.dir(p2);
console.dir(Person);
console.log(p1.eat === p2.eat);//true
原型鏈
- 構(gòu)造函數(shù)和實例對象是通過原型聯(lián)系的。
- 原型鏈的指向是可以改變的
- 如果實例對象中的屬性和原型對象中的屬性重名,使用實例對象中的屬性,但是原型對象中的屬性不會改變。
- 對象中的
__proto__指向的是自己的構(gòu)造函數(shù)的prototype. - 如果構(gòu)造函數(shù)的
prototype指向發(fā)生改變,那么實例對象中的__proto__指向也會發(fā)生改變。 - 如果實例對象的原型指向改變了,在向原型中添加方法,那么這個方法添加到了所改變指向的位置。