摘要:子類型最終回報寒潮類型對象的全部實(shí)例屬性,但是我們不得不在調(diào)用子類型構(gòu)造函數(shù)時重寫這些屬性處理引用類型共用問題組合式繼承代碼如下第二次調(diào)用第一次調(diào)用寄生組合式繼承代碼如下
面向?qū)ο笳Z言都有類的概念,但是ECMAScript沒有類的概念,所以它的對象與基于類的語言中的對象有所不同。
一、創(chuàng)建對象的幾種方式及對比 1.對象字面量與創(chuàng)建Object實(shí)例方式var person = { name:"Zhangsan", age:20, gender: "male", sayName: function(){ console.log(this.name); } }
var person = new Object(); person.name = "Zhangsan"; person.age = 20; person.gender = "male"; person.sayName = function(){ console.log(this.name); }
缺點(diǎn):使用同一個接口創(chuàng)建很多對象,會產(chǎn)生大量的重復(fù)代碼
2.工廠模式因?yàn)镋CMAScript沒有類的概念,所以用函數(shù)來封裝創(chuàng)建對象的細(xì)節(jié)
function createPerson(name,age,gender){ var o = new Object(); o.name = name; o.age = age; o.gender = gender; o.sayName = function(){ console.log(this.name); } return o; } var person1 = createPerson("Zhangsan",20,"male"); var person2 = createPerson("Lisi",24,"male"); console.log(person1 instanceof Object); //true
缺點(diǎn):工廠模式解決了創(chuàng)建多個相似對象的重復(fù)代碼問題,但沒有解決對象類型識別的問題
3.構(gòu)造函數(shù)模式function Person(name, age, gender){ this.name = name; this.age = age; this.gender = gender; this.sayName = function(){ console.log(this.name); } } var person1 = new Person("Zhangsan",20,"male"); var person2 = new Person("Lisi",24,"male"); console.log(person1 instanceof Person); //true console.log(person1 instanceof Object); //true console.log(person1.constructor == Person); //true console.log(person1.sayName == person2.sayName); //false
以這種方式調(diào)用構(gòu)造函數(shù)會經(jīng)歷以下四步:
創(chuàng)建一個新對象
將構(gòu)造函數(shù)的作用域賦給新對象
執(zhí)行構(gòu)造函數(shù)中的代碼
返回新對象
任何函數(shù),只要通過new操作符來調(diào)用,那它就可以作為構(gòu)造函數(shù);如果不通過new操作符來調(diào)用,那它就是普通函數(shù)
var person = new Person("Zhangsan",20,"male"); person.sayName(); //"Zhangsan" Person("Lisi",24,"male"); window.sayName(); //"Lisi" var o = new Object(); Person.call(o,"Wangwu",22,"female"); o.sayName(); //"Wangwu"
缺點(diǎn):每個方法都要在每個實(shí)例上重新創(chuàng)建一遍,上述例子中的sayName方法就會在每個實(shí)例中重新創(chuàng)建一遍
function Person(name, age, gender){ this.name = name; this.age = age; this.gender = gender; this.sayName = sayName; } function sayName(){ console.log(this.name); } var person1 = new Person("Zhangsan",20,"male"); var person2 = new Person("Lisi",24,"male");
上述代碼將sayName()函數(shù)的定義轉(zhuǎn)移到構(gòu)造函數(shù)外部,這樣構(gòu)造函數(shù)中的的sayName是一個指向函數(shù)的指針,因此person1、person2就共享了在全局作用域定義的同一個sayName()函數(shù)。這么做雖然解決了問題但卻帶來了新問題:如果對象需要定義很多方法那么就需要定義很多全局函數(shù),那么自定義的引用類型就絲毫沒有封裝性可言了
4.原型模式 4.1原型對象每個函數(shù)都有一個prototype屬性,這個屬性是一個指針指向一個對象,而這個對象包含可以由特定類型的所有實(shí)例共享的屬性和方法。使用原型對象的好處就是讓所有對象實(shí)例共享它所包含的屬性和方法
function Person(){ } Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.gender = "male"; Person.prototype.sayName = function(){ console.log(this.name); }; var person1 = new Person(); person1.sayName(); //Nicholas var person2 = new Person(); person2.sayName(); //Nicholas console.log(Person.prototype.isPrototypeOf(person1));//true console.log(Person.prototype.isPrototypeOf(person2));//true console.log(Object.getPrototypeOf(person1) == Person.prototype);//true console.log(Object.getPrototypeOf(person1).name);//Nicholas
當(dāng)代碼讀取某個對象的某個屬性時,先從對象實(shí)例本身開始搜索,如果找到給定名稱的屬性則返回該屬性的值;如果沒找到則搜索其指針指向的原型。當(dāng)為對象實(shí)例添加一個屬性時,則這個屬性就會屏蔽原型對象中保存的同名屬性
person1.name = "Zhangsan"; console.log(person1.name); //Zhangsan console.log(person1.hasOwnProperty("name")); //true console.log(person2.hasOwnProperty("name")); //false delete person1.name; console.log(person1.name); //Nicholas4.2原型對象賦值
function Person(){ } Person.prototype = { name:"Nicholas", age:29, gender:"male", sayName:function(){ console.log(this.name); } } var person = new Person(); console.log(person instanceof Object); //true console.log(person instanceof Person); //true console.log(person.constructor == Person); //false console.log(person.constructor == Object); //true Person.prototype.constructor = Person; console.log(person.constructor == Person); //true
使用原型對象賦值操作是會覆蓋原型對象中的constructor屬性,就會切斷原型與構(gòu)造函數(shù)之間的關(guān)聯(lián)
function Person(){ } var person = new Person(); Person.prototype = { name:"Nicholas", age:29, gender:"male", sayName:function(){ console.log(this.name); } } person.sayName(); //error
缺點(diǎn):由于原型中的所有屬性和方法都是共享的,所以對于引用類型屬性問題就比較突出
function Person(){ } Person.prototype = { constructor:Person, name:"Nicholas", age:29, gender:"male", love:["swimming","running"], sayName:function(){ console.log(this.name); } } var person1 = new Person(); var person2 = new Person(); person1.love.push("playing games"); console.log(person1.love); //["swimming", "running", "playing games"] console.log(person2.love); //["swimming", "running", "playing games"] console.log(person1.love == person2.love); //true5.組合使用構(gòu)造函數(shù)和原型模式
function Person(name,age,gender){ this.name = name; this.age = age; this.gender = gender; this.love = ["swimming","running"]; } Person.prototype = { constructor:Person, sayName:function(){ console.log(this.name); } } var person1 = new Person("Zhangsan",20,"male"); var person2 = new Person("Lisi",24,"male"); person1.love.push("playing games"); console.log(person1.love); //["swimming", "running", "playing games"] console.log(person2.love); //["swimming", "running"] console.log(person1.love == person2.love); //false
這種模式是使用最廣泛、認(rèn)同度最高的一種創(chuàng)建自定義類型的方法
6.寄生構(gòu)造函數(shù)模式function SpecialArray(name,age,gender){ var array = new Array(); array.push.apply(array,arguments); array.toPipedString = function(){ return this.join("|"); } return array; }
這種模式可以用來為原生引用類型做擴(kuò)展,寄生構(gòu)造函數(shù)模式返回的對象與構(gòu)造函數(shù)或者與構(gòu)造函數(shù)原型之間沒有關(guān)系,因此不能依賴instanceof操作符來確定對象類型
二、繼承 1.原型鏈function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function (){ return this.property; } function SubType(){ this.subproperty = false; } SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function (){ return this.subproperty; } var instance = new SubType(); console.log(instance.getSuperValue()); //true
原型鏈雖然很強(qiáng)大,可以用它來實(shí)現(xiàn)繼承,但它也存在一些問題,其中,最主要的問題來自包含引用類型值的原型;第二個問題是創(chuàng)建子類型的實(shí)例時不能向超類的構(gòu)造函數(shù)中傳遞參數(shù)。
function SuperType(){ this.colors = ["red","yellow","blue"]; } function SubType(){ } SubType.prototype = new SuperType(); var instance1 = new SubType(); instance1.colors.push("green"); console.log(instance1.colors); //["red", "yellow", "blue", "green"] var instance2 = new SubType(); console.log(instance2.colors); //["red", "yellow", "blue", "green"]2.借用構(gòu)造函數(shù)
借用構(gòu)造函數(shù)用于解決原型鏈中包含引用類型值所帶來的問題
function SuperType(){ this.colors = ["red","yellow","blue"]; } function SubType(){ SuperType.call(this); } var instance1 = new SubType(); instance1.colors.push("green"); console.log(instance1.colors); //["red", "yellow", "blue", "green"] var instance2 = new SubType(); console.log(instance2.colors); //["red", "yellow", "blue"]
問題:方法都在構(gòu)造函數(shù)中定義,因此函數(shù)復(fù)用無從談起,而且在超類原型中定義的方法對子類而言也是不可見的,結(jié)果所有類型都只能使用構(gòu)造函數(shù)模式
3.組合繼承function SuperType(name){ this.name = name; this.colors = ["red", "yellow", "blue"]; } SuperType.prototype.sayName = function(){ console.log(this.name); } function SubType(name, age){ SuperType.call(this,name); this.age = age; } SubType.prototype = new SuperType(); SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function(){ console.log(this.age); } var instance1 = new SubType("Zhangsan",20); instance1.colors.push("green"); console.log(instance1.colors); //["red", "yellow", "blue", "green"] instance1.sayName(); //Zhangsan instance1.sayAge(); //20 var instance2 = new SubType("Lisi", 24); console.log(instance2.colors); //["red", "yellow", "blue"] instance2.sayName(); //Lisi instance2.sayAge(); //24
組合繼承避免了原型鏈和借用構(gòu)造函數(shù)的缺陷,融合了他們的優(yōu)點(diǎn),成為JavaScript中最常用的繼承模式
4.原型式繼承var person = { name : "Zhangsan", colors : ["red", "yellow", "blue"] } var anotherPerson = Object.create(person); anotherPerson.name = "Lisi"; anotherPerson.colors.push("green"); var otherPerson = Object.create(person); otherPerson.name = "Wangwu"; otherPerson.colors.push("black"); console.log(person.colors); //["red", "yellow", "blue", "green", "black"] console.log(person.name); //Zhangsan
這種繼承方式在想讓一個對象與另一個對象保持類似的情況下是完全可以勝任的
5.寄生式繼承var person = { name : "Zhangsan", colors : ["red", "yellow", "blue"] } var anotherPerson = Object.create(person); anotherPerson.sayHi = function(){ console.log("hi"); } anotherPerson.sayHi();
使用寄生式繼承不能做到函數(shù)復(fù)用而降低效率
6.寄生組合式繼承組合繼承最大的問題就在于無論什么情況下都會調(diào)用兩次超類型構(gòu)造函數(shù):一次是在創(chuàng)建子類型原型的時候,另一次是在子類型構(gòu)造函數(shù)內(nèi)部。子類型最終回報寒潮類型對象的全部實(shí)例屬性,但是我們不得不在調(diào)用子類型構(gòu)造函數(shù)時重寫這些屬性(處理引用類型共用問題)
組合式繼承代碼如下:
function SuperType(name){ this.name = name; this.colors = ["red", "yellow", "blue"]; } SuperType.prototype.sayName = function(){ console.log(this.name); } function SubType(name, age){ SuperType.call(this,name); //第二次調(diào)用 this.age = age; } SubType.prototype = new SuperType(); //第一次調(diào)用 SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function(){ console.log(this.age); }
寄生組合式繼承代碼如下:
function SuperType(name){ this.name = name; this.colors = ["red", "yellow", "blue"]; } SuperType.prototype.sayName = function(){ console.log(this.name); } function SubType(name, age){ SuperType.call(this,name); this.age = age; } SubType.prototype = Object.create(SuperType.prototype); SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function(){ console.log(this.age); }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/98460.html
摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍(lán)圖或原型。在中,對象通過對類的實(shí)體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍(lán)圖或原型。在中,對象通過對類的實(shí)體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍(lán)圖或原型。在中,對象通過對類的實(shí)體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:請記住,這些書中的一些可能不是最新的,但概念和基礎(chǔ)仍應(yīng)適用。是最好的老師之一。的秘密由部分組成。在你完成這些書后,查看書籍和最好的本土?xí)? 我看過三本,第1本,第二本,第四本。第一本買的的實(shí)體書,其他兩本看的是電子書。第一本是大名鼎鼎老道寫的,書很薄,但是非常經(jīng)典。javascirpt忍者秘籍是jquery的作者寫的,也是非常經(jīng)典。you dont kown js系列也是非常好。看了...
摘要:學(xué)編程真的不是一件容易的事不管你多喜歡或是多會編程,在學(xué)習(xí)和解決問題上總會碰到障礙。熟練掌握核心內(nèi)容,特別是和多線程初步具備面向?qū)ο笤O(shè)計和編程的能力掌握基本的優(yōu)化策略。 學(xué)Java編程真的不是一件容易的事,不管你多喜歡或是多會Java編程,在學(xué)習(xí)和解決問題上總會碰到障礙。工作的時間越久就越能明白這個道理。不過這倒是一個讓人進(jìn)步的機(jī)會,因?yàn)槟阋恢辈粩嗟膶W(xué)習(xí)才能很好的解決你面前的難題...
摘要:函數(shù)式編程最后介紹一下函數(shù)式編程。函數(shù)式編程是一種歷史悠久,而又在最近頗為熱門的話題。函數(shù)式編程在面向?qū)ο笠辉~誕生以前就已經(jīng)存在,不過它在很長一段時間里都被隱藏于過程式編程面向?qū)ο笠彩沁^程式編程的一種的概念之下。 2.1 JavaScript特點(diǎn) 總結(jié)以下幾個特點(diǎn): 解釋型語言 類似與C和Java的語法結(jié)構(gòu) 動態(tài)語言 基于原型的面向?qū)ο?字面量的表現(xiàn)能力 函數(shù)式編程 解釋型語言:...
閱讀 2607·2021-10-14 09:43
閱讀 3566·2021-10-13 09:39
閱讀 3299·2019-08-30 15:44
閱讀 3150·2019-08-29 16:37
閱讀 3714·2019-08-29 13:17
閱讀 2740·2019-08-26 13:57
閱讀 1832·2019-08-26 11:59
閱讀 1253·2019-08-26 11:46