日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Classical Inheritance in JavaScript

發布時間:2025/3/21 javascript 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Classical Inheritance in JavaScript 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Douglas Crockford?? ?www.crockford.com???翻譯:ThoughtScript ?原文鏈接?http://javascript.crockford.com/inheritance.html

And you think you're so clever and classless and free ?— John Lennon

JavaScript?一種是與類無關的面向對象語言(基于對象),因此Javascript使用了基于原型的方式(原型鏈)代替傳統面向對象語言的繼承方式。這可能會讓過去習慣于使用C++、Java這類面向對象語言繼承方式的程序員感到困惑。但馬上你就能認識到實際上Javascript的原型方式確實比傳統的方式更能表達繼承關系。

JavaJavaScript

Strongly-typedLoosely-typed
StaticDynamic
ClassicalPrototypal
ClassesFunctions
ConstructorsFunctions
MethodsFunctions

但是,首先我們需要思考我們使用繼承的目的是什么?有兩個主要的方面。第一是出于類型轉換。我們希望語言環境能自動的對引用類的進行類型轉換,但有時是無法通過類型系統的安全檢查的,所以通常我們需要會對引用的對象進行顯示轉換,這對強類型語言至關重要,但是對像JavaScript這樣弱類型語言卻是無關緊要,因為Javascript中對象的引用不需要類型轉換。 第二是考慮代碼重用。通常我們通過使一系列不同對象實現相同的接口來達到重用。類繼承方式通過創建一個單獨的定義集合接口讓重用變的可能,通常我們看到一些對象非常相似,但是對象間也存在區別,主要是增加或修改了一小部分方法。傳統的類繼承方式對代碼重用的確有用,但JavaScript的原型方式更有用。 為了證明這點,我們將會介紹一些?sugar?讓我們的代碼形式類似于傳統語言的形式。并且我們將展示在傳統語言中不可行但卻非常有用的模式,最后,我們將解釋這些?sugar。

Classical Inheritance 類繼承方式

首先,我們定義一個Parenizor類,Parenizor擁有設置和獲取value變量的方法,和一個返回把value用括號包裹起來后值的toString方法。

function Parenizor(value) { this.setValue(value); }Parenizor.method('setValue', function (value) {this.value = value;return this; });Parenizor.method('getValue', function () {return this.value; });Parenizor.method('toString', function () {return '(' + this.getValue() + ')'; });

?

這樣的語法看上去有些不尋常,但這是可以很容易讓人識別這是傳統類繼承的模式。method方法接收一個方法名稱和一個方法函數,讓方法作為公共方法添加到類中。 所以現在我們可以這樣寫:

myParenizor = new Parenizor(0); myString = myParenizor.toString();

正如您所期望的,myString的值為“(0)” 現在我們定義另一個繼承自Parenizor的類,同樣的toString方法但返回“-0-”如果值為零或空。

function ZParenizor(value) { this.setValue(value); }ZParenizor.inherits(Parenizor);ZParenizor.method('toString', function () {if (this.getValue()) {return this.uber('toString'); }return"-0-"; });

inherits方法與Java的extends關鍵字作用很相似,uber方法與Java的super相似,允許方法調用父類的方法。(該名稱已被更改,以避免保留字的限制。) 所以現在我們可以這樣寫:

myZParenizor = new ZParenizor(0); myString = myZParenizor.toString();

這次,myString的值為“-0-” Javascript沒有類的概念,但是我們依舊可以按類方式的編程。

Multiple Inheritance 多重繼承

過操縱一個函數的原型對象,我們可以實現多重繼承,使我們能創建一個繼承多個類的不同方法。 復雜的多重繼承難以實現,并有可能遭受潛在的方法名稱沖突。我們可以在JavaScript中實現復雜的多重繼承,但對于這個例子中,我們將使用一種稱為Swiss Inheritance的更嚴格形式。 假設有一個NumberValue的類,具有 一個setValue 方法用來檢查value變量是否是指定范圍內的數字,并在需要的時候可以拋出異常。我們只需要ZParenizor的 setValue和setRange方法,而不需要toString方法,所以我們可以這樣寫: ZParenizor.swiss(NumberValue, 'setValue', 'setRange'); 這里只把我們請求的方法添加到了ZParenizor類中。

Parasitic Inheritance 寄生繼承

里用另一種代替繼承自Parenizor的方法來定義ZParenizor。寄生繼承并不直接從 Parenizor繼承,而是通過在ZParenizor構造器內部中調用Parenizor構造器,通過對Parenizor構造器返回的結果that進行修改,最后返回修改后的that。而這個構造器添加的是特權方法(privileged methods)而非公共方法。

function ZParenizor2(value) {var that = new Parenizor(value);that.toString = function () {if (this.getValue()) {return this.uber('toString'); }return"-0-" };return that; }

類繼承方式是 is-a(是...)?的關系,而寄生繼承是 was-a-but-now's-a(原來是……而現在是……)?的關系。在對象構造中構造器扮演了主要的角色。注意uber方法(代替super保留字)對特權方法仍然有效。

?

Class Augmentation 類擴展

??JavaScript的動態特性使我們能夠添加或替換現有類中的方法。我們能在任何時候調用method方法,不管現有的還是未來創建的類實例都將會含有新添加的方法,這樣我們在隨時都能很直接的擴展類的方法。而繼承是通過追溯的方式工作的,和類擴展是不同的。我們把這種方式命名為“Class Augmentation?”是因為想避免Java中的extends(擴展)混淆,這是兩個完全不同的概念。

Object Augmentation 對象擴展

??在靜態的面向對象語言中,假如你需要一個只是與另一已經存在對象稍有不同的對象,你必須重新定義一個新的類。但在Javascript,你可以添加單個對象的方法,而不需要定義額外的類。這樣你可以寫更少更簡單的類,這是Javascript非常強大的特性。把每一個Javascript對象現象成一張張哈希表,你可以隨時添加新的變量到哈希表中,如何變量是函數,變量就會成為對象的方法。 這樣在上面的例子中,我完全不需要用到ZParenizor類,就能以很簡單的方式修改實例對象來達到擴展對象。

myParenizor = new Parenizor(0); myParenizor.toString = function () {if (this.getValue()) {return this.uber('toString'); }return"-0-"; }; myString = myParenizor.toString();

?

這里我們沒有使用任何形式的繼承就增加了 toString方法到myParenizor?實例對象中。這是因為JavaScript是與類無關的語言,所以你可以擴展每一個獨立的實例對象。

Sugar

?

了讓上面的例子能運行,我寫了四個sugar?方法。第一個是method方法,用來把實例方法添加到類中。

Function.prototype.method = function (name, func) {this.prototype[name] = func;return this; };

這里添加了一個公共的方法到Function.prototype,這里通過類擴展的方式這樣所有的方法都可以使用method方法。這你需要一個函數名稱和函數,作為參數,將它們添加到一個函數的原型對象中。 這里返回本身(this)。當我寫一個方法,它不需要返回值時,我通常會返回它本身,這樣可以允許寫成鏈式語句的編程風格。 下一個是inherits方法,用來讓一個類繼承另一個類。inherits方法應該在兩個類定義之后調用,但在添加繼承方法之前。

Function.method('inherits', function (parent) {var d = {}, p = (this.prototype = new parent());this.method('uber', function uber(name) {if (!(name in d)) {d[name] = 0; }var f, r, t = d[name], v = parent.prototype;if (t) {while (t) {v = v.constructor.prototype;t -= 1; }f = v[name];} else {f = p[name];if (f == this[name]) {f = v[name]; } }d[name] += 1;r = f.apply(this, Array.prototype.slice.apply(arguments, [1]));d[name] -= 1;return r; });return this; });

?

再來,我們擴展Function類。我們創建parent類的實例對象做為新的prototype。在添加uber方法到prototype的同時修正constructor?字段。 uber方法將會在自己的prototype中查找指定的方法。這個方法在寄生繼承或對象擴展的情況下會被調用執行。如果使用的是類繼承方式,那么我們要找到parent的prototype中的函數。return語句調用了函數的apply方法來調用該函數,同時顯示地設置this并傳遞一個參數數組。參數(如果有的話)可以從arguments數組中獲得。不幸的是,arguments數組并不是一個真正的數組,所以我們必須再次調用apply來調用數組中的slice方法。 最后是swiss方法:

Function.method('swiss', function (parent) {for (var i = 1; i < arguments.length; i += 1) {var name = arguments[i];this.prototype[name] = parent.prototype[name]; }return this; });

?

swiss方法遍歷arguments參數對象。通過每一個參數名稱name,他從parent原型中拷貝成員到自身類的原型中。

Conclusion 結論

??JavaScript可以傳統語言方式那樣使用,但它也有豐富獨特的表達繼承的方式。我們已經了解了 類繼承方式,Swiss繼承方式,寄生繼承方式,類擴展和對象擴展。這一系列代碼重用的模式來自被認為比Java更小,更簡單的Javascript。 傳統語言中的對象是固定的(hard),要在對象中添加新的成員變量的唯一方式就是創建新的類。但在Javascript中,對象是靈活(soft),添加一個新的成員到JavaScript對象中只需要作簡單的賦值。 由于JavaScript中的對象是如此靈活,你必須對類層次結構有不同的認識。深層次(Deep hierarchies )是不適當的,淺層次(Shallow hierarchies )更具執行效率和可讀性。 到現在我已經寫了8年的JavaScript,期間我發現我從來沒有使用過uber方法。調用父類成員(super)的想法在傳統模式中是相當重要的,但是在原型和函數式的模式中這看起來并不是很有必要。從現在看來早期我支持傳統模式中super的嘗試是一個錯誤。

轉載于:https://www.cnblogs.com/leejersey/p/4357667.html

總結

以上是生活随笔為你收集整理的Classical Inheritance in JavaScript的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩无码专区 | 中文字幕亚洲第一 | 黑人操日本女人 | 日韩精品短片 | 手机av不卡 | 国产码视频| www.麻豆av.com| 国产一区二区视频在线观看 | 四虎国产成人永久精品免费 | 日本人妻换人妻毛片 | 日韩一级一级 | 亚洲国产欧美日韩 | 亚洲+小说+欧美+激情+另类 | 夫妻啪啪呻吟x一88av | 国产情侣免费视频 | 久久在线精品 | 乱子伦视频在线看 | 足疗店女技师按摩毛片 | 激情国产精品 | 人人妻人人澡人人爽欧美一区双 | 伊人伊人伊人伊人 | 伊人精品在线 | 一级大黄毛片 | 免费a级大片| 日韩性插| av手机在线播放 | 国产精品一二三区在线观看 | 最新成人在线 | 中字幕视频在线永久在线观看免费 | 丰满人妻一区二区三区性色 | 国产影音先锋 | 国内精品卡一卡二卡三 | 久久福利视频导航 | 亚洲91色 | 日日爽爽 | 肉色超薄丝袜脚交一区二区 | 西西大胆午夜视频 | 免费av看片 | a在线观看视频 | 久久婷婷五月国产色综合激情 | 九九热精品视频 | 欧美日韩一区二区三区不卡 | 国产精品一区免费观看 | 成人毛片视频免费看 | 午夜影院一区 | 经典杯子蛋糕日剧在线观看免费 | 久久久久久无码午夜精品直播 | 国产不卡二区 | 精品一区二区中文字幕 | 久久天 | 久久看av | 天天综合网天天综合色 | 国产精品热| 鲁一鲁色一色 | 欧美精品不卡 | 免费在线你懂的 | 欧美猛交xxx | 天堂视频免费 | 污污视频在线观看免费 | 日韩无马| 国产不卡二区 | 波多野结衣免费看 | 岛国不卡| 国产欧美在线一区 | 色播五月激情 | 国产精品电影一区二区 | 三级av| 精品国产一区在线 | 韩国福利一区 | 夜夜操av| 久久久久久国产精品免费播放 | 林雅儿欧洲留学恋爱日记在线 | 日韩av在线一区二区 | 无遮挡裸光屁屁打屁股男男 | 亚洲污视频 | 免费黄色网址大全 | 麻豆视频在线观看免费 | 97人妻精品一区二区三区 | 国产最新在线观看 | 欧美日韩一区二区三区电影 | 天天爱综合 | 亚洲一区欧美激情 | 国产一区不卡在线 | 久久婷五月 | 国产夫妻在线视频 | av网站观看 | 日本在线不卡一区二区三区 | 岛国av噜噜噜久久久狠狠av | 欧洲一级视频 | 草莓巧克力香氛动漫的观看方法 | a级在线视频 | 操久久久 | 91精品国产91久久久久久久久久久久 | 亚洲乱码国产乱码精品精的特点 | 性一交一黄一片 | 四虎视频国产精品免费入口 | 欧美aa在线观看 | 久操这里只有精品 | 激情区|