摘要:在創(chuàng)建子類實(shí)例時(shí),不能向超類型的構(gòu)造函數(shù)中傳遞參數(shù)。構(gòu)造函數(shù)繼承子類傳進(jìn)的值是基本思想是在子類構(gòu)造函數(shù)的內(nèi)部調(diào)用超類或父類型構(gòu)造函數(shù)。繼承保證構(gòu)造函數(shù)指針指向如果想同時(shí)繼承多個(gè),還可使用添加屬性的方式類繼承,
OOP:Object Oriented Programming 面向?qū)ο缶幊獭?/pre>題外話:面向?qū)ο蟮姆秶鷮?shí)在太大,先把這些大的東西理解理解。1.什么是對(duì)象?根據(jù)高程和權(quán)威指南上的定義,對(duì)象是一組沒(méi)有特定順序的值,我們可以把對(duì)象看成是從字符串到值的映射。2.怎樣理解原型和原型鏈?原型:
根據(jù)權(quán)威指南上的定義:每一個(gè)js對(duì)象(null除外)都和另一個(gè)對(duì)象相關(guān)聯(lián), “另一個(gè)”對(duì)象就是我們熟知的原型,每一個(gè)對(duì)象都從原型上繼承屬性。原型也是對(duì)象。 通俗點(diǎn)講,就是一個(gè)擁有prototype屬性、且這個(gè)屬性指向函數(shù)的原型對(duì)象的對(duì)象。原型的好處就是:原型上的方法和屬性會(huì)被所有實(shí)例所共享。原型鏈:
當(dāng)訪問(wèn)某個(gè)實(shí)例屬性或方法時(shí),會(huì)先自身對(duì)象中查找,查不到時(shí)再往當(dāng)前對(duì)象原型上找; 若依然沒(méi)找到,則會(huì)繼續(xù)往原型對(duì)象的原型上找,一直到找到結(jié)果或者找到Object.prototype為止也沒(méi)找到, 然后這時(shí)就會(huì)返回undefined,這么一個(gè)鏈?zhǔn)讲檎疫^(guò)程形成的結(jié)構(gòu)就叫原型鏈。每個(gè)對(duì)象都有一個(gè)__proto__屬性,函數(shù)也是對(duì)象,所以函數(shù)也有;3.面向?qū)ο蟮娜筇匦允鞘裁矗?/b>
每個(gè)函數(shù)都有一個(gè)prototype屬性,而實(shí)例對(duì)象沒(méi)有。封裝,繼承,多態(tài)(指一個(gè)方法可以有多種調(diào)用方式:例如有參或無(wú)參)4.創(chuàng)建對(duì)象有哪些方式? (1).對(duì)象字面量let obj={};
(2).Object方式let obj=new Object();
(3).Object.createlet obj=Object.create({}/null);
注意!!前面這三種方式的的構(gòu)造函數(shù)都是Object,而Object已經(jīng)是原型鏈的最頂端了,所以O(shè)bject.prototype都為undefined。(4).工廠模式可以用實(shí)例的__proto__.constructor查看構(gòu)造函數(shù)是否指向Object構(gòu)造函數(shù)。
function person(name,job){ let o={}; o.name=name; o.job=job; o.sayName=function(){ console.log(this.name); } return o; } let p1=person("nagi","sleep"); console.log(p1.constructor); // 指向Object p1 instanceof person; // false;優(yōu)缺點(diǎn):
這種模式雖然解決了量產(chǎn)對(duì)象的問(wèn)題,但卻無(wú)法獲知當(dāng)前對(duì)象是何類型 (例如類型:Array,Math等內(nèi)置對(duì)象,或者BOM(window)/DOM的宿主對(duì)象,又或者自定義對(duì)象等)注意點(diǎn):函數(shù)首字母不用大寫(xiě)。
(5).構(gòu)造函數(shù)模式function Person(name,job){ this.name=name; this.job=job; this.sayName=function(){ console.log(this.name); } } let p1=new Person("nagi","sleep"); console.log(p1.constructor); // 指向Person p1 instanceof Person; // true與工廠模式區(qū)別:
a.沒(méi)有顯式創(chuàng)建對(duì)象; b.直接將屬性和方法賦給了this對(duì)象 c.不有return語(yǔ)句;拓展:new操作符做了些什么?
a.創(chuàng)建一個(gè)新對(duì)象; b.將構(gòu)造函數(shù)的作用域賦給新對(duì)象(因此this就指向一這個(gè)新對(duì)象); c.執(zhí)行構(gòu)造函數(shù)中的代碼(為這個(gè)新對(duì)象添加屬性); d.返回新對(duì)象(默認(rèn)返回當(dāng)前對(duì)象,除非有顯示返回某個(gè)對(duì)象)優(yōu)缺點(diǎn):
首先是解決了工廠模式中不能判斷類型的問(wèn)題; 但缺點(diǎn)是每實(shí)例一次的同時(shí)還會(huì)把方法重新創(chuàng)建一遍,造成內(nèi)存資源浪費(fèi); 其次,因構(gòu)造函數(shù)與其它函數(shù)的唯一區(qū)別就是調(diào)用方式不一樣,所以當(dāng)被當(dāng)作普通函數(shù)調(diào)用時(shí),其內(nèi)部的this會(huì)指向全局,引發(fā)作用域問(wèn)題。(6).原型模式function Person(){}; // 寫(xiě)法一: Person.prototype.name="nagi"; Person.prototype.job="sleep"; Person.prototype.sayName=function(){ console.log(this.name); }; // 寫(xiě)法二:注意,這種直接更改原型指向的寫(xiě)法,會(huì)改變constructor指向,指向Object構(gòu)造函數(shù) /* Person.prototype={ // constructor:Person, name:"nagi", job:"sleep", sayName:function (){ console.log(this.name) } }*/ let p1=new Person();優(yōu)缺點(diǎn):
優(yōu)點(diǎn):解決了上述構(gòu)造函數(shù)的缺點(diǎn),原型對(duì)象上的屬性和方法為所有實(shí)例所共享。 缺點(diǎn): a.缺點(diǎn)也是所有實(shí)例共享方法和屬性,因此其中一個(gè)實(shí)例更改了引用類型的屬性值時(shí),其他的實(shí)例也會(huì)被迫改變。(屬性) b.默認(rèn)情況下所有實(shí)例都取得相同的屬性值。(7).組合模式(結(jié)合構(gòu)造函數(shù)和原型模式)function Person(name,job){ this.name=name; this.job=job; } Person.prototype.sayName=function(){ console.log(this.name); } let p1=new Person("nagi","sleep");4.對(duì)象繼承方式有哪些? (1).原型鏈繼承function Parent(){ this.name="nagi"; this.colors=["red","blue","green"]; } Parent.prototype.sayName=function(){ console.log(this.name); } function Child(){ this.job="sleep"; }; Child.prototype=new Parent(); // 要注意:這種重寫(xiě)原型鏈的寫(xiě)法是會(huì)切斷構(gòu)造函數(shù)與最初原型之間的聯(lián)系的, // 意味著此時(shí)Child.prototype.constructor指向Parent var child=new Child();這種方式的基本思想就是利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法。問(wèn)題點(diǎn):
a.上述例子中,通過(guò)原型繼承方式繼承相當(dāng)于專門(mén)創(chuàng)建了一個(gè)Child.prototype.colors的屬性, 因?yàn)橐妙愋偷脑蛯傩詴?huì)被所有實(shí)例共享,也就意味著Child的所有實(shí)例都會(huì)共享colors這一屬性, 當(dāng)其中一實(shí)例修改它的值時(shí),那么其他的實(shí)例的值也會(huì)跟著被改變。 b.在創(chuàng)建子類實(shí)例時(shí),不能向超類型的構(gòu)造函數(shù)中傳遞參數(shù)。鑒于此,實(shí)際很少多帶帶用原型鏈繼承。超類型:比如Child類繼承了Parent類的屬性,那么Parent就是Child的超類(也叫父類)。(2).構(gòu)造函數(shù)繼承(call/apply)function Parent(name){ console.log(`子類傳進(jìn)的name值是:${name}`) this.name="nagi"; this.colors=["red","blue","green"]; } Parent.prototype.sayName=function(){ console.log(this.name); } function Child(){ Parent.call(this,"Bob") this.job="sleep"; }; var child1=new Child(); var child2=new Child();基本思想是在子類構(gòu)造函數(shù)的內(nèi)部調(diào)用超類(或父類)型構(gòu)造函數(shù)。優(yōu)缺點(diǎn):
優(yōu)勢(shì):解決了原型鏈的兩個(gè)問(wèn)題; 缺點(diǎn): a. 方法都在構(gòu)造函數(shù)定義的話,那函數(shù)復(fù)用就無(wú)從談起了。 b. 父類在原型中定義的方法,對(duì)于子類型來(lái)說(shuō)是不可見(jiàn)的。鑒于此,構(gòu)造函數(shù)也很少用。[捂臉](3).組合繼承(即原型鏈+構(gòu)造函數(shù))function Parent(name){ this.name=name; this.job="sleep"; this.colors=["red","blue","green"]; } Parent.prototype.sayName=function(){ console.log(this.name); } function Child(name){ Parent.call(this,name); this.job="eat"; } Child.prototype=new Parent(); Child.prototype.constructor=Child; let child1=new Child("nagi"); let child2=new Child("Bob");其實(shí)現(xiàn)思路是用原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承,而借助構(gòu)造函數(shù)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承。 優(yōu)點(diǎn):在前兩者基礎(chǔ)上,補(bǔ)足了構(gòu)造函數(shù)和原型鏈的缺點(diǎn),是比較常用的方式。(4). Object.create繼承function Parent(name){ this.name=name; this.job="sleep"; this.colors=["red","blue","green"]; } Parent.prototype.sayName=function(){ console.log(this.name); } function Child(){ Parent.call(this); // 保證構(gòu)造函數(shù)指針指向Child } Child.prototype=Object.create(Parent.prototype,{name:{value:"nagi"},job:{value:"eat"}}) // 如果想同時(shí)繼承多個(gè),還可使用Object.assign()添加屬性 // Object.assign(A.prototype, B.prototype); let child=new Child();(5)ES6的extends方式類繼承,class A extends B
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/99321.html
摘要:構(gòu)造函數(shù)所以,就有了畸形的繼承方式原型鏈繼承三原型鏈繼承改變構(gòu)造函數(shù)的原型對(duì)象繼承了屬性以上例子中,暴露出原型鏈繼承的兩個(gè)問(wèn)題包含引用類型數(shù)據(jù)的原型屬性,會(huì)被所有實(shí)例共享,基本數(shù)據(jù)類型則不會(huì)。 前言 眾所周知,JavaScript 中,沒(méi)有 JAVA 等主流語(yǔ)言類的概念,更沒(méi)有父子類繼承的概念,而是通過(guò)原型對(duì)象和原型鏈的方式實(shí)現(xiàn)繼承。 于是,我們這一篇講一講 JS 中的繼承(委托)。 ...
摘要:由構(gòu)造函數(shù)返回的對(duì)象就是表達(dá)式的結(jié)果。如果構(gòu)造函數(shù)沒(méi)有顯式返回一個(gè)對(duì)象,則使用步驟創(chuàng)建的對(duì)象。運(yùn)算符返回一個(gè)布爾值,表示對(duì)象是否為某個(gè)構(gòu)造函數(shù)的實(shí)例。 面向?qū)ο?本人能力有限,有誤請(qǐng)斧正 本文旨在復(fù)習(xí)面向?qū)ο?不包含es6) 本文學(xué)習(xí)思維 創(chuàng)建對(duì)象的方式,獲取對(duì)象屬性 構(gòu)造函數(shù),構(gòu)造函數(shù)的new 做了什么 原型與原型對(duì)象 原型鏈 繼承(借用構(gòu)造繼承、原型繼承、組合繼承、寄生組合繼承)...
摘要:構(gòu)造函數(shù)通常首字母大寫(xiě),用于區(qū)分普通函數(shù)。這種關(guān)系常被稱為原型鏈,它解釋了為何一個(gè)對(duì)象會(huì)擁有定義在其他對(duì)象中的屬性和方法。中所有的對(duì)象,都有一個(gè)屬性,指向?qū)嵗龑?duì)象的構(gòu)造函數(shù)原型由于是個(gè)非標(biāo)準(zhǔn)屬性,因此只有和兩個(gè)瀏覽器支持,標(biāo)準(zhǔn)方法是。 從這篇文章開(kāi)始,復(fù)習(xí) MDN 中級(jí)教程 的內(nèi)容了,在初級(jí)教程中,我和大家分享了一些比較簡(jiǎn)單基礎(chǔ)的知識(shí)點(diǎn),并放在我的 【Cute-JavaScript】系...
摘要:組合構(gòu)造原型模式將自身屬性于構(gòu)造函數(shù)中定義,公用的方法綁定至原型對(duì)象上原型對(duì)象的解釋每一個(gè)函數(shù)創(chuàng)建時(shí)本身內(nèi)部會(huì)有一個(gè)固有的原型對(duì)象,可以通過(guò)函數(shù)名去訪問(wèn),而其原型對(duì)象又有一個(gè)屬性指針指向該函數(shù)。 每次遇到JS面對(duì)對(duì)象這個(gè)概念,關(guān)于繼承及原型,腦海里大概有個(gè)知識(shí)框架,但是很不系統(tǒng)化,復(fù)習(xí)下,將其系統(tǒng)化,內(nèi)容涉及到對(duì)象的創(chuàng)建,原型鏈,以及繼承。 創(chuàng)建對(duì)象 兩種常用方式,其余的比較少見(jiàn)工廠模...
摘要:所以繼承了對(duì)象的所有方法,當(dāng)你用時(shí),會(huì)先查一下它的構(gòu)造函數(shù)的原型對(duì)象有沒(méi)有有方法,沒(méi)查到的話繼續(xù)查一下的原型對(duì)象有沒(méi)有這個(gè)方法。 普通函數(shù)與構(gòu)造函數(shù)的區(qū)別 在命名規(guī)則上,構(gòu)造函數(shù)一般是首字母大寫(xiě),普通函數(shù)遵照小駝峰式命名法。 在函數(shù)調(diào)用的時(shí)候: function fn() { } 構(gòu)造函數(shù):1. new fn( ) 2 .構(gòu)造函數(shù)內(nèi)部會(huì)...
閱讀 2293·2021-11-15 11:37
閱讀 2962·2021-09-01 10:41
閱讀 797·2019-12-27 11:58
閱讀 753·2019-08-30 15:54
閱讀 719·2019-08-30 13:52
閱讀 2936·2019-08-29 12:22
閱讀 1080·2019-08-28 18:27
閱讀 1458·2019-08-26 18:42