摘要:繼承一共有三種方式類式繼承原型式繼承摻元類類式繼承可以被裝扮成使用類式繼承的語言。在使用原型式繼承時,不需要用類來定義對象的結(jié)構(gòu),只需直接創(chuàng)建一個對象即可。原型式繼承更能節(jié)約內(nèi)存。
今天整理面試題的時候看見一道題叫講一下繼承,雖然繼承以前也看過書,也在用,但是居然無法總結(jié)性、系統(tǒng)地回答這個問題,于是趕緊把《JavaScript設(shè)計模式》扒拉出來看看。
為什么需要繼承在設(shè)計類的時候,能夠減少重復(fù)性代碼,并且能盡量弱化對象間的耦合。可以在現(xiàn)有類的基礎(chǔ)上進行設(shè)計并充分利用已經(jīng)具備的各種方法,而對設(shè)計的修改也更為輕松。
繼承一共有三種方式:類式繼承、原型式繼承、摻元類
JavaScript可以被裝扮成使用類式繼承的語言。通過用函數(shù)來聲明類、用關(guān)鍵字 new 來創(chuàng)建實例,JavaScript中的對象也能模仿Java或C++中的對象。
首先創(chuàng)造一個簡單的類聲明,及對該類的實例化:
// 創(chuàng)建 Person 類 function Person (name) { this.name = name; } Person.prototype.getName = function () { return this.name; }; // 實例化 Person 類 var reader = new Person ("John Smith"); reader.getName(); // John Smith
創(chuàng)建繼承 Person 的類 Author :
// 創(chuàng)建繼承 Person 的類 Author function Author (name,books) { Person.call(this,name); this.book = books; } // 派生子類 Author.prototype = new Person(); Author.prototype.constructor = Author; Author.prootype.getBooks = function () { return this.book; };
在默認情況下,所有原型對象都會自動獲得一個 constructor (構(gòu)造函數(shù))屬性,這個屬性是一個指向 prototype 屬性所在函數(shù)的指針。
為了簡化類的聲明。可以把派生子類的整個過程包裝在一個名為 extend 的函數(shù)中,作用是基于一個給定的類結(jié)構(gòu)創(chuàng)建一個新的類。
// extend 函數(shù) function extend(subClass,superClass) { var F = function() {}; F.prototype = superClass.prototype; subClass.prototype = new F(); subClass.prototype.constructor = subClass; // 確保超類的 constructor 屬性被設(shè)置正確 subClass.superclass = superClass.prototype; if(superClass.prototype.constructor == Object.prototype.constructor) { superClass.prototype.constructor = superClass; } }
那么 Author 的繼承可以改寫為:
function Author (name,books) { Author.superClass.contructor.call(this,name); this.books = books; } extend(Author,Person); // 調(diào)用 extend 函數(shù) Author.prootype.getBooks = function () { return this.book; };原型式繼承
原型式繼承和類式繼承截然不同。在學(xué)習(xí)原型式繼承時,最好忘掉自己關(guān)于類和實例的一切知識,只從對象的角度來考慮。
在使用原型式繼承時,不需要用類來定義對象的結(jié)構(gòu),只需直接創(chuàng)建一個對象即可。這個對象隨后可以被新的對象重用,這得益于原型鏈查找的工作機制,該對象被稱為原型對象。
下面使用原型式繼承來重新設(shè)計 Person 和 Author
// Person 原型對象 var Person = { name: "default name", getName: function() { return this.name; } };
Person 現(xiàn)在是一個對象字面量,其中定義了所有類 Person 對象都要具備的屬性和方法,并為他們提供了默認值。clone 函數(shù)可以用來創(chuàng)建新的類 Person 對象,該函數(shù)會創(chuàng)建一個空對象,而該對象的原型對象被設(shè)置為 Person。
// Author 原型對象 var Author = clone(Person); Author.books = []; // Default value Author.getBooks = function () { return this.books; };
一個克隆并非原型對象的一份完全獨立的副本,它只是一個以那個對象為原型對象的空對象。對繼承而來的成員有讀和寫的不對等性:
var authorClone = clone(Author); alert(authorClone.name); // default name (連接到 Person.name) authorClone.name = "new name"; alert(authorClone.name); // new name (連接到 authorClone.name) authorClone.books.push("new book"); // 在這里,想authorClone.books數(shù)組添加 // 新元素實際上是把這個元素添加到 // Author.books數(shù)組中。 authorClone.books = []; authorClone.books.push("new book");
這也就說明了為什么必須為通過引用傳遞的數(shù)據(jù)類型的屬性創(chuàng)建新的副本。在以上例子中,向authorClone.books數(shù)組添加新元素實際上是把這個元素添加到Author.books數(shù)組中。這可不是什么好事,因為對那個值的修改不僅會影響到 Author,而且會影響到所有機場了Author但還未改寫那個屬性的默認值的對象。在改變所有那些數(shù)組和對象的成員之前,必須先為其創(chuàng)建新的副本。
類似繼承和原型式繼承的對比包括JavaScript程序員在內(nèi)的整個程序員群體對類式繼承都比較熟悉。
原型式繼承更能節(jié)約內(nèi)存。在原型鏈中查找成員的方式使得所有克隆出來的對象都共享每個屬性和唯一一份實例,只有在直接設(shè)置了某個克隆出來的對象的屬性和方法時,情況才會有所變化。而類似繼承方式中創(chuàng)建的每一個對象在內(nèi)存中都有自己的一套屬性的副本。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/90936.html
摘要:這正是我們想要的太棒了毫不意外的,這種繼承的方式被稱為構(gòu)造函數(shù)繼承,在中是一種關(guān)鍵的實現(xiàn)的繼承方法,相信你已經(jīng)很好的掌握了。 你應(yīng)該知道,JavaScript是一門基于原型鏈的語言,而我們今天的主題 -- 繼承就和原型鏈這一概念息息相關(guān)。甚至可以說,所謂的原型鏈就是一條繼承鏈。有些困惑了嗎?接著看下去吧。 一、構(gòu)造函數(shù),原型屬性與實例對象 要搞清楚如何在JavaScript中實現(xiàn)繼承,...
摘要:中的繼承并不是明確規(guī)定的,而是通過模仿實現(xiàn)的。繼承中的繼承又稱模擬類繼承。將函數(shù)抽離到全局對象中,函數(shù)內(nèi)部直接通過作用域鏈查找函數(shù)。這種范式編程是基于作用域鏈,與前面講的繼承是基于原型鏈的本質(zhì)區(qū)別是屬性查找方式的不同。 這一節(jié)梳理對象的繼承。 我們主要使用繼承來實現(xiàn)代碼的抽象和代碼的復(fù)用,在應(yīng)用層實現(xiàn)功能的封裝。 javascript 的對象繼承方式真的是百花齊放,屬性繼承、原型繼承、...
摘要:繼承前言作為一門輕量級的腳本語言在和的橫空出世之后將其推向的新的高度雖然中出現(xiàn)的新的生成對象的類語法格式但依然為的語法糖而我們依然有必要從的原生實現(xiàn)入手來了解它的繼承實現(xiàn)方式給出了更加簡潔的固定的類聲明方式有興趣的可以查看阮一峰的入門下面給 javascript繼承 前言 javascript作為一門輕量級的腳本語言在ES6和node.js的橫空出世之后將其推向的新的高度,雖然 ES6...
摘要:我們有了構(gòu)造函數(shù)之后,第二步開始使用它構(gòu)造一個函數(shù)。來個例子這種方式很簡單也很直接,你在構(gòu)造函數(shù)的原型上定義方法,那么用該構(gòu)造函數(shù)實例化出來的對象都可以通過原型繼承鏈訪問到定義在構(gòu)造函數(shù)原型上的方法。 來源: 個人博客 白話解釋 Javascript 原型繼承(prototype inheritance) 什么是繼承? 學(xué)過面向?qū)ο蟮耐瑢W(xué)們是否還記得,老師整天掛在嘴邊的面向?qū)ο笕筇?..
摘要:和構(gòu)造函數(shù)前面提到,是個內(nèi)置隱藏屬性,雖然在可以通過訪問,但是其設(shè)計本意是不可被讀取和修改的,那么我們?nèi)绾卫迷玩渷斫⒗^承關(guān)系提供了關(guān)鍵字。到這兒,思路就清晰了,怎么讓對象和對象的相連實現(xiàn)繼承只需把的構(gòu)造函數(shù)的連接到就行了。 什么是繼承? 大多數(shù)人使用繼承不外乎是為了獲得這兩點好處,代碼的抽象和代碼的復(fù)用。代碼的抽象就不用說了,交通工具和汽車這類的例子數(shù)不勝數(shù),在傳統(tǒng)的OO語言中(...
閱讀 1700·2021-11-02 14:47
閱讀 3648·2019-08-30 15:44
閱讀 1334·2019-08-29 16:42
閱讀 1731·2019-08-26 13:53
閱讀 935·2019-08-26 10:41
閱讀 3458·2019-08-23 17:10
閱讀 597·2019-08-23 14:24
閱讀 1717·2019-08-23 11:59