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