摘要:使用調(diào)用構(gòu)造函數(shù),將構(gòu)造函數(shù)的作用域賦給新對(duì)象指向新對(duì)象構(gòu)造函數(shù)模式的特點(diǎn)使用構(gòu)造函數(shù)創(chuàng)建的對(duì)象實(shí)例有特定的類型。說(shuō)明是的原型屬性。
這是兩年前寫的筆記,自己都有遺忘,相信也會(huì)有人不明白,貼在這里。
都是紅寶書上的內(nèi)容,在比較難理解的地方加了一些示例和說(shuō)明。
es中定義對(duì)象為:無(wú)需屬性的集合、其屬性可以包含基本值、對(duì)象或者函數(shù)。
創(chuàng)建對(duì)象 Object實(shí)例創(chuàng)建對(duì)象最簡(jiǎn)單的方法是創(chuàng)建一個(gè)Object的實(shí)例。
var person =new Object(); person.name="Mike"; person.age=12; person.job="student"; person.sayName=function(){ };對(duì)象字面量
var person={ name:"mike", age:10, job:"student", sayName:function(){ alert(this.name); } };
Object實(shí)例和對(duì)象字面量都可以用來(lái)創(chuàng)建單個(gè)對(duì)象,
但是當(dāng)要?jiǎng)?chuàng)建多個(gè)對(duì)象就會(huì)產(chǎn)生大量重復(fù)的代碼,由此產(chǎn)生了工廠模式。
工廠模式的特點(diǎn)是用函數(shù)來(lái)封裝創(chuàng)建對(duì)象的細(xì)節(jié),對(duì)外以接口的方式調(diào)用。
function createPerson(name,age,job){ var obj = new Object(); obj.name=name; obj.age=age; obj.job=job; obj.sayName=function(){ alert(this.name); } return obj; } var person1=createPerson("Mike",12,"student");
工廠模式雖然解決了創(chuàng)建相似對(duì)象重復(fù)代碼的問題,
但同時(shí)還存在一個(gè)問題:如何知道對(duì)象的類別?由此產(chǎn)生構(gòu)造函數(shù)模式
function CreatePerson(name,age,job){ this.name=name; this.age=age; this.job=job; this.sayName=function(){ alert(this.name); } } var person1= new CreatePerson("Mi",13,"student"); var person2= new CreatePerson("Mike",12,"student"); alert(person2.constructor==CreatePerson);//true alert(person1 instanceof CreatePerson);//true alert(person2 instanceof CreatePerson);//true alert(person2 instanceof Object);//true 使用instanceof來(lái)檢測(cè)對(duì)象的類型
構(gòu)造函數(shù)沒有返回值,沒有顯示地創(chuàng)建對(duì)象。
使用new調(diào)用構(gòu)造函數(shù),將構(gòu)造函數(shù)的作用域賦給新對(duì)象(this指向新對(duì)象)
構(gòu)造函數(shù)模式的特點(diǎn):使用構(gòu)造函數(shù)創(chuàng)建的對(duì)象(實(shí)例)有特定的類型。這也是構(gòu)造函數(shù)模式勝過(guò)工廠模式的地方
構(gòu)造函數(shù)模式的問題:構(gòu)造函數(shù)中方法,在不同的實(shí)例中是不同的funciton實(shí)例,也就是說(shuō)不同實(shí)例中有不同function(雖然他們的功能相同),
但是這并不是我們希望看到的,更何況function中還有this(指向?qū)嵗淖饔糜颍酝耆珱]有必要把功能相同function綁定到特定的實(shí)例上。
由此產(chǎn)生了原型模式!
大boss來(lái)了,接著說(shuō)下去
關(guān)于原型的定義,摘自紅寶書:每個(gè)函數(shù)都有一個(gè)prototype(原型)屬性,這個(gè)屬性是一個(gè)指針,指向一個(gè)對(duì)象,而這個(gè)對(duì)象的用途是包含可以由特定類型的所有實(shí)例共享的屬性和方法。
好長(zhǎng)一句話!有點(diǎn)暈?直接上代碼:
function Person(){ } Person.prototype.name="mike"; Person.prototype.age=12; Person.prototype.job="Software Engneer"; Person.prototype.sayName=function(){ alert(this.name); } var person1=new Person(); alert(Person1.prototype.isPrototypeOf(person5));//true檢驗(yàn)實(shí)例與原型之間的關(guān)系 person1.sayName();//mike var person2=new Person(); alert(person1.sayName()==person2.sayName());//true var person6=new Person(); person6.name="ssss"; alert(person6.hasOwnProperty("ssss"));//true原型鏈查找屬性或方法:
首先查找實(shí)例屬性:即定義在子類構(gòu)造函數(shù)中或直接添加在實(shí)例上的屬性
然后查找子類原型屬性:包括子類自有的原型屬性和,父類的實(shí)例屬性(子類的原型是父類的實(shí)例)(這也就是原型鏈繼承的缺點(diǎn),父類的實(shí)例屬性全變成子類的原型屬性,那就是所有子類實(shí)例共享的,如果又是引用類型,就出大事了。所以很少多帶帶使用原型鏈)
最后查找父類的原型屬性
function SuperType(){ this.name="super"; this.job="student"; } SuperType.prototype.getSuperValue=function(){ alert(this.name); } SuperType.prototype.sex="man"; function SubType(){ this.age=12; } SubType.prototype=new SuperType(); SubType.prototype.getSubValue=function(){ alert(this.age); } //var person=new SubType(); var instance1=new SubType alert(instance1 instanceof SubType);//true alert(instance1 instanceof SuperType);//true alert(SubType.prototype.isPrototypeOf(instance1));//true alert(SuperType.prototype.isPrototypeOf(instance1));//true person.getSuperValue(); alert(person.constructor==SubType);//false子類的實(shí)例的原型對(duì)象沒有constructor屬性 alert(person instanceof SubType); alert(person instanceof SuperType); alert(person.job); alert(person.constructor);//sub的原型指向super的原型,super的原型的constuctor是superType,所以person的 alert(person.hasOwnProperty("name"));//false alert("name" in person);//true 說(shuō)明name是sub的原型屬性。 alert(person.hasOwnProperty("sex"));//false alert("sex" in person);//true 說(shuō)明name是sub的原型屬性。,父類中的全部屬性都是子類的原型屬性 var person1=new SuperType();; alert(person1.constructor);//
解決原型鏈缺點(diǎn)的方法:借用構(gòu)造函數(shù)
借用構(gòu)造函數(shù)function SuperType(name){ this.colors=["red","yellow","green"]; this.name=name; } function SubType(){ SuperType.call(this,"Mike"); this.age=10; } var instance1=new SubType(); instance1.colors.push("aa"); alert(instance1.colors); alert(instance1 instanceof SubType);//true alert(instance1 instanceof SuperType);//false alert(SubType.prototype.isPrototypeOf(instance1));//true alert(SuperType.prototype.isPrototypeOf(instance1));//false var instance2=new SubType(); alert(instance2.colors);//["red","yellow","green"];
在新實(shí)例的環(huán)境中調(diào)用Super構(gòu)造函數(shù)
var instance3=new SubType(); alert(instance3.hasOwnProperty("name")); alert(instance3.hasOwnProperty("age"));
在子類中call(借調(diào))父類的構(gòu)造函數(shù)實(shí)際上就是為子類添加了實(shí)例屬性(原來(lái)在父類中的實(shí)例屬性)
即父類的實(shí)例屬性變成了子類的實(shí)例屬性(原型鏈繼承中,父類的實(shí)例屬性變成了子類的原型屬性)
function SuperType(name){ this.colors=["red","yellow","green"]; this.name=name; } SuperType.prototype.sayName=function(){ alert(this.name); } function SubType(name,age){ SuperType.call(this,"Kiko"); this.age=age; } SubType.prototype=new SuperType(); SubType.prototype.constructor=SubType; SubType.prototype.sayAge=function(){ alert(this.age); } var instance1=new SubType("Kiko",12); //instance1.sayName(); //instance1.colors.push("ss"); //alert("colors" in instance1);//有屬性 //alert(instance1.hasOwnProperty("colors")) //實(shí)例屬性 沒有這句話的時(shí)候//SuperType.call(this,"Kiko");,,是原型屬性 //有了這句話變成了實(shí)例屬性 //alert(instance1.colors); //instance1.sayAge(); alert(instance1 instanceof SubType);//true alert(instance1 instanceof SuperType);//true alert(SubType.prototype.isPrototypeOf(instance1));//true alert(SuperType.prototype.isPrototypeOf(instance1));//true alert(Object.keys(SubType.prototype));//colors,name,constructor,sayAge alert(Object.keys(instance1));//colors,name,age
這兩句說(shuō)明第一:SubType.prototype=new SuperType();父類的所有屬性都變成了子類的原型屬性
第二:SuperType.call(this,"Kiko");,在子類的構(gòu)造函數(shù)中重寫了父類的實(shí)例屬性,即父類的實(shí)例屬性變成了子類的實(shí)例屬性
第三:p149:每當(dāng)代碼讀取對(duì)象中的某個(gè)屬性時(shí),都會(huì)執(zhí)行一次搜索,先查找實(shí)例屬性,再查找原型屬性
第四:因此,組合繼承中父類中的實(shí)例屬性既是子類的實(shí)例屬性也是子類的原型屬性,但是在每次使用對(duì)象時(shí),查找到實(shí)例屬性就截止了,
所以表現(xiàn)為父類中的實(shí)例屬性變成了子類中的實(shí)例屬性(實(shí)例屬性覆蓋了原型對(duì)象上的同名屬性)
var instance2=new SubType("hihi",13);
//alert(instance2.colors);
function object(o){ function F(){} F.prototype=o; return new F(); } var person={ name:"Mike", friends:["kiko","Court","Van"] }; var anotherPerson=object(person); alert(anotherPerson.name);// anotherPerson.friends.push("ss"); var yetAnotherPerson=object(person); alert(yetAnotherPerson.friends);//["kiko","Court","Van","ss"]寄生式繼承
function createAnother(original){ var clone=object(original); clone.sayHi=function(){ alert("hi"); } return clone; } var anotherPerson1=createAnother(person); anotherPerson.sayHi();//hi
使用寄生式繼承來(lái)為對(duì)象添加函數(shù),會(huì)由于不能復(fù)用而降低效率,這一點(diǎn)與構(gòu)造函數(shù)模式很類似(同名的方法是不同的function實(shí)例)
寄生組合式繼承組合式的缺點(diǎn)是兩次調(diào)用超類的構(gòu)造函數(shù):
一,SubType.prototype=new SuperType();父類的所有屬性都變成了子類的原型屬性
二:SuperType.call(this,"Kiko");,在子類的構(gòu)造函數(shù)中重寫了父類的實(shí)例屬性,即父類的實(shí)例屬性變成了子類的實(shí)例屬性
寄生組合式目的是為了省掉第一步多繼承的實(shí)例屬性,在第一步時(shí)只繼承父類的原型屬性,第二步繼承實(shí)例屬性
function object(o){ function F(){} F.prototype=o; return new F(); } function inheritPrototype(SubType,SuperType){ var prototype=object(SuperType.prototype); prototype.constructor=SubType; SubType.prototype=prototype; } function SuperType(name){ this.name=name; this.colors=["red","blue","yellow"]; } SuperType.prototype.sayName=function(){ alert(this.name); } SuperType.prototype.job="student"; function SubType(name,age){ SuperType.call(this,name);//(2)繼承實(shí)例屬性 this.age=age; } inheritPrototype(SubType,SuperType);//(3)繼承原型屬性 SubType.prototype=new SuperType();//(1)把父類的原型屬性和實(shí)例屬性都繼承為原型屬性了 SubType.prototype.sayAge=function(){ alert(this.age); } var instance1=new SubType(); alert("name" in instance1);//有屬性true alert(instance1.hasOwnProperty("name"));//false不是實(shí)例屬性
這兩句話檢驗(yàn)是否是原型屬性,1true,2false,原型屬性,1ture,2true實(shí)例屬性
寄生組合式,name會(huì)是實(shí)例屬性
組合式,把(3)換成(1)name確實(shí)也是實(shí)例屬性,那是因?yàn)?2)重新調(diào)用了SuperType,覆蓋了原型中的同名屬性。
可以把(2)去掉,發(fā)現(xiàn)name變成了原型屬性。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/100766.html
摘要:一些額外的全局函數(shù)命名空間對(duì)象接口和構(gòu)造函數(shù)與沒有典型的關(guān)聯(lián),但卻是有效的。最后有幾點(diǎn)需要說(shuō)明的是每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象,原型對(duì)象都包含一個(gè)指向構(gòu)造函數(shù)的指針,而實(shí)例都包含一個(gè)指向原型對(duì)象的內(nèi)部指針。 文章來(lái)源:小青年原創(chuàng)發(fā)布時(shí)間:2016-07-03關(guān)鍵詞:JavaScript,原型鏈,jQuery類庫(kù)轉(zhuǎn)載需標(biāo)注本文原始地址: http://zhaomenghuan.githu...
摘要:原文地址詳解的類博主博客地址的個(gè)人博客從當(dāng)初的一個(gè)彈窗語(yǔ)言,一步步發(fā)展成為現(xiàn)在前后端通吃的龐然大物。那么,的類又該怎么定義呢在面向?qū)ο缶幊讨校愂菍?duì)象的模板,定義了同一組對(duì)象又稱實(shí)例共有的屬性和方法。這個(gè)等同于的屬性現(xiàn)已棄用。。 前言 生活有度,人生添壽。 原文地址:詳解javascript的類 博主博客地址:Damonare的個(gè)人博客 ??Javascript從當(dāng)初的一個(gè)彈窗語(yǔ)言,一...
摘要:原文地址詳解的類博主博客地址的個(gè)人博客從當(dāng)初的一個(gè)彈窗語(yǔ)言,一步步發(fā)展成為現(xiàn)在前后端通吃的龐然大物。那么,的類又該怎么定義呢在面向?qū)ο缶幊讨校愂菍?duì)象的模板,定義了同一組對(duì)象又稱實(shí)例共有的屬性和方法。這個(gè)等同于的屬性現(xiàn)已棄用。。 前言 生活有度,人生添壽。 原文地址:詳解javascript的類 博主博客地址:Damonare的個(gè)人博客 ??Javascript從當(dāng)初的一個(gè)彈窗語(yǔ)言,一...
摘要:這樣每個(gè)實(shí)例獨(dú)享自己的屬性,并和其他同類型的實(shí)例共享方法構(gòu)造函數(shù)原型以上這種方式定義的類型,可以通過(guò)來(lái)判斷一個(gè)實(shí)例是否是類型的實(shí)際上是通過(guò)實(shí)例的原型鏈來(lái)判斷一個(gè)對(duì)象是否某個(gè)類型的實(shí)例的,具體的細(xì)節(jié)后面會(huì)詳細(xì)介紹。 JavaScript面向?qū)ο缶幊? 如何定義自定義類型 首先需要明確,JavaScript并不是傳統(tǒng)意義上的OO語(yǔ)言,它并沒有class的概念, 而是包含了另一套異常強(qiáng)大的...
閱讀 2570·2021-09-06 15:02
閱讀 3200·2021-09-02 10:18
閱讀 2822·2019-08-30 15:44
閱讀 685·2019-08-30 15:43
閱讀 1948·2019-08-30 14:08
閱讀 2758·2019-08-30 13:16
閱讀 1397·2019-08-26 13:52
閱讀 931·2019-08-26 12:21