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