摘要:之二關(guān)于原型開篇我記得初學(xué)時,最難懂的概念就是的原型,而且這個概念在筆試面試中常常提到,因此今天我們把這個概念拿出來,好好聊一聊。
之二:關(guān)于js原型 1. 開篇
我記得初學(xué)js時,最難懂的概念就是js的原型,而且這個概念在筆試面試中常常提到,
因此今天我們把這個概念拿出來,好好聊一聊。
在仔細(xì)講解之前,我們先來看一道題,這道題來自JavaScript高級程序設(shè)計中原型鏈那一節(jié):
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(); alert(instance.getSuperValue());
請大家猜一猜最后alert出的結(jié)果是什么?
大家先思考一下再看下面的內(nèi)容。
2. 幾個知識點如果上面的題沒解出來,也不要灰心喪氣,因為有可能有的人解出來的結(jié)果也不一定對。
要想弄明白原型等一系列概念,其實只需要記住這幾個知識點。
_proto_:任何一個對象Object都有_proto_,它是每一個對象的私有屬性,是天生自帶的。
prototype:不是任何對象都有prototype,只有構(gòu)造函數(shù)有prototype,是后天賦予的。
其實只需要記住一句話:調(diào)用一個對象的屬性或方法,一但這個對象中沒有,就去這個對象的_proto_中查找。這個對象的_proto_指向自己構(gòu)造函數(shù)的prototype屬性
然后我們來看一張圖:
再來看一個例子:
var Person = function () { this.sleep = "Zzzzz..." } Person.prototype.sayHello = function () { console.log("hello world"); } var zhangsan = new Person(); zhangsan.sayHello();
其實zhangsan這個對象下面只有一個sleep屬性,是沒有sayHello方法的。
但是通過原型鏈查找會查zhangsan._proto_也就是查找它的構(gòu)造函數(shù)的Person.prototype,Person.prototype下有sayHello這個方法,所以會在控制臺輸出hello world
所以啦,萬變不離其宗!
除了最新的ES6外,js其實是沒有繼承和類的概念的,因此想要達(dá)到j(luò)s的繼承就要通過模擬的方式。
這里將主要介紹三種繼承的方式:純原型鏈繼承,借用構(gòu)造函數(shù)繼承,組合繼承
多說無益,來個簡單暴力直接的方式,直接上代碼:
function Father() { this.likeFood= ["牛排","餃子","啤酒","可樂"] } Father.prototype.saylikeFood = function () { console.log(this.likeFood); }; function Son() { } Son.prototype = new Father(); var zhangsan = new Son(); zhangsan.likeFood.push("西瓜"); zhangsan.saylikeFood(); // ["牛排", "餃子", "啤酒", "可樂", "西瓜"]
Ok,這就是純原型鏈的繼承方式,其實說白了就是把繼承的對象的prototype等于繼承自構(gòu)造函數(shù)的實例。
但是這樣的方式有問題。接著上面的代碼的后面我們再寫:
var lisi = new Son(); lisi.saylikeFood(); // ["牛排", "餃子", "啤酒", "可樂", "西瓜"]
看出問題了吧,zhangsan直接修改了其構(gòu)造函數(shù)的likeFood,
導(dǎo)致我們再實例的對象也收到了修改的影響,
因此這種繼承方式有缺陷
還是多說無益,我們直接來看例子,上代碼:
function Father(name) { this.name = name; this.sayName = function () { console.log(this.name); } } function Son(name, age) { Father.call(this, name); this.age = age; } var zhangsan = new Son("zhangsan", 17);
這種繼承方式并沒有利用到原型以及原型鏈的概念,它主要利用call的特性,call的第一個參數(shù)傳入this,后面的參數(shù)傳入函數(shù)所需的參數(shù)。
這種方式歸根結(jié)底其實就是在實例一個對象的時候,向這個對象的上面添加所需的屬性和方法。
不信的話可以輸出zhangsan看一下
但是其實這種方式也有問題,什么問題呢?
按照這種方式,每次new一個對象,就是實例化一個對象,都會向這個對象身上添加一堆屬性和方法。
添加屬性是沒問題的,但是每次在對象身上添加的方法,這個函數(shù)就要重寫一次。
函數(shù)不能進(jìn)行復(fù)用,這就是最大的問題!
這次要多說兩句,組合繼承其實分別是擁有以上兩種方法的優(yōu)點,同時也規(guī)避了以上兩種方法的缺點。
這種方法的應(yīng)用是最廣泛的,是最普遍的,舉個栗子來看一下:
function Father(name) { this.name = name; } Farther.prototype.sayName = function () { console.log(this.name); } function Son(name, age) { Farther.call(this, name); this.age = age; } Son.prototype = new Father(); Son.constructor = Son; Son.prototype.sayage = function () { console.log(this.age); } var zhangsan = new Son();
來看一下,這種方式不錯吧!
其實除了組合繼承外,還有兩種繼承方式:原型式繼承和寄生式繼承,
這兩種方式感興趣的同學(xué)可以自行了解一下
抱歉,這篇這么遲才出來,其實應(yīng)該早早完事的。
我最近買了一本《學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法》再看,我準(zhǔn)備新開辟一個專欄來寫一下我的學(xué)習(xí)筆記。
下一次我決定和大家講講閉包的事。
本期的內(nèi)容是原創(chuàng)的,但其實主要是看了《JavaScript高級程序設(shè)計》的啟發(fā)!
建議你也去看書,讀一下這本書的第六章的繼承那一部分,相信你也會深有啟發(fā)。
加油!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/87875.html
摘要:避免脆弱的基類問題。紅牌警告沒有提到上述任何問題。單向數(shù)據(jù)流意味著模型是單一的事實來源。單向數(shù)據(jù)流是確定性的,而雙向綁定可能導(dǎo)致更難以遵循和理解的副作用。原文地址 1. 你能說出兩種對 JavaScript 應(yīng)用開發(fā)者而言的編程范式嗎? 希望聽到: 2. 什么是函數(shù)編程? 希望聽到: 3. 類繼承和原型繼承的不同? 希望聽到 4. 函數(shù)式編程和面向?qū)ο缶幊痰膬?yōu)缺點? ...
摘要:所支持的面向?qū)ο缶幊贪ㄔ屠^承。發(fā)明于年的就是首批支持函數(shù)式編程的語言之一,而演算則可以說是孕育了這門語言。即使在今天,這個家族的編程語言應(yīng)用范圍依然很廣。 1. 能說出來兩種對于 JavaScript 工程師很重要的編程范式么? JavaScript 是一門多范式(multi-paradigm)的編程語言,它既支持命令式(imperative)/面向過程(procedural)編程...
摘要:所支持的面向?qū)ο缶幊贪ㄔ屠^承。發(fā)明于年的就是首批支持函數(shù)式編程的語言之一,而演算則可以說是孕育了這門語言。即使在今天,這個家族的編程語言應(yīng)用范圍依然很廣。 1. 能說出來兩種對于 JavaScript 工程師很重要的編程范式么? JavaScript 是一門多范式(multi-paradigm)的編程語言,它既支持命令式(imperative)/面向過程(procedural)編程...
摘要:所支持的面向?qū)ο缶幊贪ㄔ屠^承。發(fā)明于年的就是首批支持函數(shù)式編程的語言之一,而演算則可以說是孕育了這門語言。即使在今天,這個家族的編程語言應(yīng)用范圍依然很廣。 1. 能說出來兩種對于 JavaScript 工程師很重要的編程范式么? JavaScript 是一門多范式(multi-paradigm)的編程語言,它既支持命令式(imperative)/面向過程(procedural)編程...
閱讀 1598·2021-11-04 16:11
閱讀 3309·2021-09-09 11:33
閱讀 1558·2019-08-30 15:54
閱讀 619·2019-08-30 15:44
閱讀 3174·2019-08-30 15:43
閱讀 2554·2019-08-30 13:06
閱讀 1698·2019-08-29 17:00
閱讀 895·2019-08-29 15:33