摘要:引言上篇文章介紹原型,這篇文章接著講繼承,嘔心瀝血之作,大哥們點(diǎn)個(gè)贊呀明確一點(diǎn)并不是真正的面向?qū)ο笳Z(yǔ)言,沒(méi)有真正的類,所以我們也沒(méi)有類繼承實(shí)現(xiàn)繼承有且僅有兩種方式,和原型鏈在介紹繼承前我們先介紹下其他概念函數(shù)的三種角色一個(gè)函數(shù),有三種角色。
引言
上篇文章介紹原型,這篇文章接著講繼承,嘔心瀝血之作,大哥們點(diǎn)個(gè)贊呀
明確一點(diǎn):JavaScript并不是真正的面向?qū)ο笳Z(yǔ)言,沒(méi)有真正的類,所以我們也沒(méi)有類繼承
實(shí)現(xiàn)繼承==有且僅有兩種方式,call和原型鏈==
在介紹繼承前我們先介紹下其他概念
函數(shù)的三種角色一個(gè)函數(shù),有三種角色。
當(dāng)成普通函數(shù),當(dāng)成構(gòu)造函數(shù)(類),當(dāng)成對(duì)象
function Person (nickname) { var age = 15 //當(dāng)普通函數(shù)使 **重點(diǎn):稱為私有屬性** this.age = 30 //當(dāng)構(gòu)造函數(shù)使 **重點(diǎn):稱為實(shí)例屬性** } Person.prototype.age = 50 //當(dāng)構(gòu)造函數(shù)使 **重點(diǎn):稱為原型屬性** Person.age =100 //當(dāng)對(duì)象使 **重點(diǎn):稱為靜態(tài)屬性**
==我個(gè)人把屬性和方法統(tǒng)一稱為廣義上的屬性,所以上面說(shuō)法其實(shí)不嚴(yán)謹(jǐn)==
大家猜一猜Array.isArray是靜態(tài)方法還是原型方法,為啥?Array.push呢?
繼承的方式繼承原則:
使用call繼承實(shí)例上的屬性
使用原型鏈繼承原型上的屬性
子類需要有自己的原型,父類也必須要有自己的原型,子實(shí)例在自己的原型上找不到屬性的時(shí)候才會(huì)到父原型上去找(這也就是子類.prototype = 父類.prototype不行的原因,因?yàn)樗鼈冎虚g沒(méi)有==“緩沖”==,改了子類原型相當(dāng)于就改了父類原型!)
const Person = function (name) { this.name = name } Person.prototype.introduce = function(){ Object.entries(this).forEach((item)=>{ console.log(`my ${item[0]} is ${item[1]}`) }) } const Student = function (name,age) { Person.call(this,name) this.age = age } Student.prototype = new Person() //這里new了父類一次,增加了額外開(kāi)銷 Student.prototype.constructor = Student //這一句可以讓student.constructor.name由Person變?yōu)镾tudent 方便確認(rèn)構(gòu)造函數(shù) let student = new Student("小明",15) student.introduce() 繼承父類原型方法的同時(shí)繼承父類實(shí)例上的屬性 //my name is 小明 //my age is 15
組合繼承有一個(gè)缺點(diǎn),會(huì)額外new父類一次,增加了額外開(kāi)銷(想一想如果父類特別大這消耗會(huì)有多大)
Object.create繼承(原型式繼承)從名字也看出來(lái)了,借用原型鏈繼承,實(shí)例能通過(guò)__proto__追蹤到傳入到參數(shù)obj,所以源碼如下
//Oject.create(obj)
Object.create = function(obj){
var fn = funcion(){} fn.prototype = obj reurturn new fn()
}
var A = Object.create(B) //A能找到B
=再次強(qiáng)調(diào)一遍,A通過(guò)原型鏈最終到B=
我們?cè)倏匆幌陆M合繼承的原型鏈 Student-->Person的實(shí)例-->Person
還記得我們?cè)谧铋_(kāi)始繼承原則中說(shuō)的緩沖嗎,Person的實(shí)例就是這么一個(gè)緩沖 但是缺點(diǎn)就是構(gòu)造這么一個(gè)緩沖開(kāi)銷大了
所以我們有一個(gè)優(yōu)化手段
Student.prototype = new Person() //未優(yōu)化的時(shí)候 Person實(shí)例充當(dāng)原型鏈的中間對(duì)象(緩沖) ------------------------- Student.prototype = Object.create(Person.prototype) //優(yōu)化后 一個(gè)繼承Person的空對(duì)象充當(dāng)中間對(duì)象(緩沖) ------------------------ Student.prototype.__proto__ = Person.prototype //當(dāng)然也有人這么寫 道理都是一樣,Student.prototype.__proto__做緩沖new干了啥
既然new在“類”的創(chuàng)建里面必須使用,那么我們就說(shuō)一下new到底干了啥事情
1.創(chuàng)建一個(gè)對(duì)象o繼承構(gòu)造函數(shù)
2.讓構(gòu)造函數(shù)的this變?yōu)閛,并執(zhí)行構(gòu)造函數(shù),將返回值設(shè)置為k
3.如果k
//仿寫new function new1(func) { var o = Object.create(func.prototype) var k = func.apply(o,arguments[1]) return typeof k === "object"? k: o } const x = new1(Student,["張三"]) x.name //"張三" x.eat //"i am hungry,i want to eat!"
我們回過(guò)頭再分析一下構(gòu)造函數(shù)模式繼承
const Person = function (name) { this.name = name } const Students = function (name) { Person.call(this,name) //this是student實(shí)例 } const xm = new Students("小明") //分析這里干了什么 console.log(xm) //Students?{name: "小明"}
1.讓空對(duì)象o繼承Students(o能訪問(wèn)Students的原型)
2.student執(zhí)行,執(zhí)行Person的代碼,this是o,并且傳入name, o.name="小明"返回的k是undefined
3.返回o,也就是返回{name:"小明"}
class Person { } class Student extends person{ }
在babel es2015-loose模式下編譯后的源碼如下
"use strict"; function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } var Person = function Person() { }; var Student = /*#__PURE__*/ function (_person) { _inheritsLoose(Student, _person); function Student() { return _person.apply(this, arguments) || this; } return Student; }(person);
嚴(yán)格模式下,高級(jí)單例模式返回一個(gè)Student, 可以看到Person的實(shí)例屬性用的Person的構(gòu)造函數(shù)+apply繼承的
原型屬性用的_inheritsLoose這個(gè)方法繼承的
_inheritsLoose方法貌似就是我們之前說(shuō)的寄生組合繼承
我們知道vue里面的數(shù)組有變異方法,變異方法有啥功能呢,就拿push來(lái)說(shuō),一方面數(shù)組會(huì)變,另外一方面有響應(yīng)式(假設(shè)觸發(fā)render方法)
思路:APO編程思想
數(shù)組之所以有push方法,是因?yàn)锳rray.prototype上有push方法
我們需要實(shí)現(xiàn)自己的push方法,掛在Array.prototype上對(duì)原型鏈追蹤進(jìn)行攔截,但是呢又不能改變?cè)玩溕蠈?duì)非變異方法
原型鏈?zhǔn)疽猓?/p>
Vue里面添加過(guò)監(jiān)控的數(shù)組實(shí)例--->我們自己實(shí)現(xiàn)的變異方法-->原來(lái)的Array.prototype
const arrList = ["push","pop","shift","unshfit","reverse","sort","splice"] const render = ()=>{console.log("響應(yīng)式,渲染視圖")} const proto = Object.create(Array) arrList.forEach((method)=>{ proto[method] = function(){ render() Array.prototype[method].call(this,...arguments) } }) var data = [1,2,3] data.__proto__ = proto //mvvm響應(yīng)式原理,如果添加響應(yīng)式的目標(biāo)是數(shù)組,我就執(zhí)行這個(gè)操作 data.push(4) // 響應(yīng)式,渲染視圖,(data[1,2,3,4])總結(jié)
本節(jié)詳細(xì)介紹了繼承的原理以及優(yōu)化,對(duì)于es6的繼承語(yǔ)法糖也做了剖析。同時(shí)介紹了一下mvvm下數(shù)組借用繼承實(shí)現(xiàn)響應(yīng)式的用法,由于本人水平有限,如果有什么不對(duì)的地方,歡迎留言指出。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/109760.html
摘要:同理,原型鏈也是實(shí)現(xiàn)繼承的主要方式的只是語(yǔ)法糖。原型對(duì)象也可能擁有原型,并從中繼承方法和屬性,一層一層以此類推。利用構(gòu)造函數(shù)小明張三張三小明缺點(diǎn)每次實(shí)例化都需要復(fù)制一遍函數(shù)到實(shí)例里面。寄生構(gòu)造函數(shù)模式只有被類出來(lái)的才能用。 showImg(https://segmentfault.com/img/bVbo4hv?w=1800&h=1000); 引言 最近又攀登了一下JS三座大山中的第二...
摘要:核心知識(shí)點(diǎn)梳理數(shù)據(jù)篇看了一些資料,結(jié)合高程和對(duì)核心知識(shí)點(diǎn)進(jìn)行了梳理。所以,一共有種聲明變量的方法。凡是在聲明之前就使用這些變量,就會(huì)報(bào)錯(cuò)。還是那句話,建議大家掌握核心知識(shí)點(diǎn),細(xì)枝末節(jié)的東西就隨意啦。 JS核心知識(shí)點(diǎn)梳理——數(shù)據(jù)篇 showImg(https://segmentfault.com/img/bVbo4hv?w=1800&h=1000); 看了一些資料,結(jié)合ES6、高程和MD...
摘要:引言滿滿的干貨,面試必系列,參考大量資料,并集合自己的理解以及相關(guān)的面試題,對(duì)核心知識(shí)點(diǎn)中的作用域閉包上下文進(jìn)行了梳理。本篇重點(diǎn)介紹閉包和。所以,有另一種說(shuō)法認(rèn)為閉包是由函數(shù)和與其相關(guān)的引用環(huán)境組合而成的實(shí)體。 showImg(https://segmentfault.com/img/bVbo4hv?w=1800&h=1000); 引言 滿滿的干貨,面試必bei系列,參考大量資料,并集...
摘要:而且在超類型的原型中定義的方法,對(duì)子類型而言也是不可見(jiàn)的,結(jié)果所有類型都只能使用構(gòu)造函數(shù)模式。在主要考慮對(duì)象而不是自定義類型和構(gòu)造函數(shù)的情況下,這個(gè)模式也不錯(cuò)。 寫在前面 注:這個(gè)系列是本人對(duì)js知識(shí)的一些梳理,其中不少內(nèi)容來(lái)自書籍:Javascript高級(jí)程序設(shè)計(jì)第三版和JavaScript權(quán)威指南第六版,感謝它們的作者和譯者。有發(fā)現(xiàn)什么問(wèn)題的,歡迎留言指出。 1.原型鏈 將原型鏈作...
摘要:英文原文中本來(lái)是,而翻譯成第一類公民其實(shí)就是一種比喻。所以,通過(guò)上述的結(jié)果,我們發(fā)現(xiàn)在中不管我們是用構(gòu)造函數(shù)創(chuàng)建的對(duì)象還是用本身提供的數(shù)據(jù)類型創(chuàng)建的對(duì)象都源自于。使用可以解除函數(shù)體內(nèi)代碼和函數(shù)名的耦合狀態(tài)。 作為一個(gè)Jser,不光要會(huì)用js,還要明白它的運(yùn)行原理,不然就會(huì)一直停留在表面。 函數(shù)在JavaScript中被稱作第一等公民,這個(gè)第一等公民是什么鬼?看看知乎上是怎么回答的。就像...
閱讀 1767·2021-11-24 09:39
閱讀 1560·2021-11-16 11:54
閱讀 3501·2021-11-11 16:55
閱讀 1666·2021-10-14 09:43
閱讀 1449·2019-08-30 15:55
閱讀 1236·2019-08-30 15:54
閱讀 3425·2019-08-30 15:53
閱讀 1343·2019-08-30 14:18