封裝:將屬性和方法封裝進(jìn)對(duì)象
構(gòu)造函數(shù):函數(shù)中有this指向?qū)ο?/p>
function Cat(name,color) {
this.name = name;
this.color = color;
}
從構(gòu)造函數(shù)生成實(shí)例:
var cat1 = new Cat("老大","yellow");//this 綁定在實(shí)例對(duì)象上
var cat2 = new Cat("老二","red");//this 綁定在實(shí)例對(duì)象上
生成實(shí)例的時(shí)候,為每個(gè)實(shí)例開(kāi)辟一個(gè)內(nèi)區(qū)域。
cat1.name;//"老大"
cat2.color;//"red"
實(shí)例對(duì)象有個(gè)constructor屬性,默認(rèn)指向構(gòu)造函數(shù):
cat1.constructor === Cat;//true
cat2.constructor === Cat;//true
每個(gè)實(shí)例對(duì)象有一個(gè)內(nèi)存區(qū)域,當(dāng)實(shí)例對(duì)象之間有共同的屬性時(shí),就會(huì)造成內(nèi)存的浪費(fèi):
function Cat(name,color) {
this.name = name;
this.color = color;
this.type = "cat";
this.eat = function() { console.log("eat"); };
}
var cat1 = new Cat("老大","yellow");//每個(gè)cat實(shí)例都有一個(gè)相同屬性值的屬性和方法,浪費(fèi)內(nèi)存
var cat2 = new Cat("老二","red");
解決方法:prototype:
構(gòu)造函數(shù)的prototype屬性是一個(gè)對(duì)象,這個(gè)對(duì)象的屬性和方法都會(huì)被實(shí)例所繼承;
因此,可以將屬性值相同的屬性或者方法給這個(gè)對(duì)象,則實(shí)例對(duì)象因?yàn)槔^承,自然就擁有了這些屬性和方法:
function Cat(name,color) {
this.name = name;
this.color = color;
}
Cat.prototype.type = "cat";
Cat.prototype.eat = function() { console.log("eat"); };
var cat1 = new Cat("老大","yellow");
cat1.type;//"cat"
cat1.eat();//"eat"
這些屬性和方法存放在prototype對(duì)象中,實(shí)例只是繼承這些屬性和方法,無(wú)需占用新的內(nèi)存,節(jié)約了內(nèi)存空間。
所有實(shí)例的type屬性和eat()方法,其實(shí)都是同一個(gè)內(nèi)存地址,指向prototype對(duì)象,因此就提高了運(yùn)行效率。
isPrototypeOf 判斷某個(gè)prototype對(duì)象和某個(gè)實(shí)例的關(guān)系:
Cat.isPrototypeOf(cat1);//true
hasOwnProperty(); 判讀某個(gè)屬性是不是自身的屬性而不是繼承的屬性
cat1.hasOwnProperty("name");//true
cat1.hasOwnProperty("type");//false
in 判斷某個(gè)對(duì)象有沒(méi)有這個(gè)屬性(包括繼承來(lái)的):
"name" in cat1;//true
"type" in cat1;//true
構(gòu)造函數(shù)的繼承(五種方法):
法一:apply方法
function Animal() {
this.type = "animal";
}
funciton Cat(name,color) {
Animal.apply(this,arguments);//將Animal中的this指向這個(gè)Cat構(gòu)造函數(shù),則Cat自然可以使用Animal中的屬性和方法
this.name = name;
this.color = color;
}
var cat1 = new Cat("老大","yellow");
cat1.type;//"animal"
法二:prototype指向一個(gè)實(shí)例對(duì)象
function Animal() {
this.type = "animal";
}
funciton Cat(name,color) {
this.name = name;
this.color = color;
}
Cat.prototype = new Animal();//Cat 的prototype對(duì)象指向要繼承的構(gòu)造函數(shù)的實(shí)例,則這個(gè)實(shí)例擁有的屬性和方法,Cat.prototype也擁有了,然后Cat的實(shí)例cat1繼承Cat.prototype的所有屬性和方法,自然就繼承了Animal的屬性和方法
Cat.prototype.constructor === Animal;//true,改變了constructor屬性應(yīng)有的值
Cat.prototype.constructor = Cat;//將prototype 的 constructor屬性重新賦值為Cat
Cat.prototype.constructor === Cat;//true
var cat1 = new Cat("老大","yellow");
cat1.type;//"animal"
cat1.constructor === Cat;//true;
存在問(wèn)題:要先生成一個(gè)Animal實(shí)例,占用一定的內(nèi)存空間;
解決方法:法三:直接繼承prototype
function Animal() {};
Animal.prototype.type = "animal";
funciton Cat(name,color) {
this.name = name;
this.color = color;
}
Cat.prototype = Animal.prototype;
var cat1 = new Cat("老大","yellow");
cat1.type;//"animal"
Cat.prototype.constructor === Animal;//true 因?yàn)镃at.prototype指向Animal.prototype了
cat1.constructor ===Animal;//true 實(shí)例的constructor也被修改了
Cat.prototype.constructor = Cat;//需要重新將constructor屬性指向原來(lái)的構(gòu)造函數(shù)
Cat.prototype.constructor === Cat;//true;
cat1.constructor === Cat;//true;
Animal.prototype.constructor === Cat;//true 但是Cat的constructor對(duì)了,Animal的constructor卻被改變了,因?yàn)镃at.prototype直接指向Animal.prototype,修改Cat.prototype的constructor屬性也會(huì)修改Animal.prototype的constructor屬性
解決方法:法四:利用空對(duì)象作為中介:
function Animal() {};
Animal.prototype.type = "animal";
function Cat(name,color) {
this.name = name;
this.color = color;
}
var F = function() {};
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor === Animal;//true Cat.prototype指向F的實(shí)例,所以Cat.prototype的構(gòu)造函數(shù)就是F實(shí)例的構(gòu)造函數(shù),F(xiàn)實(shí)例的構(gòu)造函數(shù)默認(rèn)指向F.prototype的構(gòu)造函數(shù),因?yàn)镕.prototype指向Animal.prototype,所以F.prototype的構(gòu)造函數(shù)就是Animal.prototype的構(gòu)造函數(shù),所以Cat.prototype的構(gòu)造函數(shù)就是Animal
Cat.prototype.constructor = Cat;//重新正確指向原來(lái)的構(gòu)造函數(shù),因?yàn)镃at.prototype只是指向F的一個(gè)實(shí)例,所以只修改了F實(shí)例的構(gòu)造函數(shù),而不修改F.prototype和Animal.prototype的構(gòu)造函數(shù)
Cat.prototype.constructor === Cat;//true
Animal.prototype.constructor === Animal;//true
var cat1 = new Cat("老大","yellow");
cat1.type;//"animal"
法五:拷貝繼承
把父對(duì)象的所有屬性和方法拷貝進(jìn)子對(duì)象
function Animal(){}
Animal.prototype.species = "動(dòng)物";
function extend2(Child, Parent) {
var p = Parent.prototype;
var c = Child.prototype;
for (var i in p) {
c[i] = p[i];
}
c.uber = p;
}
function Cat(name,color) {
this.name = name;
this.color = color;
}
extend2(Cat, Animal);
var cat1 = new Cat("大毛","黃色");
alert(cat1.species);//"動(dòng)物"
Cat不繼承Animal的構(gòu)造函數(shù)中屬性和方法,只繼承Animal.prototype的屬性和方法