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