JavaScript是一門強行聲稱物件導向的語言,而繼承是物件導向的一大主要特性,以下是我給大家整理的,有興趣的同學可以去看看。
概述JavaScript的所有對象,都有自己的繼承鏈。也就是說,每個物件都繼承另一個對象,該物件稱為「原型」(prototype)物件。只有null除外,它沒有自己的原型物件。
原型物件的重要性在於,如果A物件是B物件的原型,那麼B物件可以拿到A物件的所有屬性和方法。 Object.getPrototypof方法用於取得目前物件的原型物件。
var p = Object.getPrototypeOf(obj);
上面程式碼中,物件p就是物件obj的原型物件。
Object.create方法用來產生一個新的對象,繼承指定對象。
var obj = Object.create(p);
上面程式碼中,新產生的obj物件的原型就是物件p。
非標準的__proto__屬性(前後各兩個底線),可以改寫某個物件的原型物件。但是,應該盡量少用這個屬性,而是用Object.getPrototypeof()和Object.setPrototypeOf(),進行原型物件的讀寫操作。
var obj = {}; var p = {}; obj.__proto__ = p; Object.getPrototypeOf(obj) === p // true
上面程式碼透過__proto__屬性,將p物件設為obj物件的原型。
下面是一個實際的例子。
var a = {x: 1}; var b = {__proto__: a}; b.x // 1
上面程式碼中,b物件透過__proto__屬性,將自己的原型物件設為a對象,因此b物件可以拿到a物件的所有屬性和方法。 b物件本身並沒有x屬性,但是JavaScript引擎透過__proto__屬性,找到它的原型物件a,然後讀取a的x屬性。
new指令透過建構函式新建實例對象,實質就是將實例物件的原型綁定建構函式的prototype屬性,然後在實例物件上執行建構函式。
var o = new Foo(); // 等同于 var o = new Object(); o.__proto__ = Foo.prototype; Foo.call(o);
原型物件自己的__proto__屬性,也可以指向其他對象,從而一級一級地形成「原型鏈」(prototype chain)。
var a = { x: 1 }; var b = { __proto__: a }; var c = { __proto__: b }; c.x // 1
要注意的是,一級級向上,在原型鏈尋找某個屬性,對性能是有影響的。所尋找的屬性在越上層的原型對象,對效能的影響越大。如果尋找某個不存在的屬性,將會遍歷整個原型鏈。
this的動作指向不管this在哪裡定義,使用的時候,它總是指向當前對象,而不是原型對象。
var o = { a: 2, m: function(b) { return this.a + 1; } }; var p = Object.create(o); p.a = 12; p.m() // 13
上面程式碼中,p物件的m方法來自它的原型物件o。這時,m方法內部的this對象,不指向o,而是指向p。
建構函數的繼承這個小節介紹,如何讓一個建構函數,繼承另一個建構子。
假定有一個Shape建構子。
function Shape() { this.x = 0; this.y = 0; } Shape.prototype.move = function (x, y) { this.x += x; this.y += y; console.info('Shape moved.'); }; Rectangle构造函数继承Shape。 function Rectangle() { Shape.call(this); // 调用父类构造函数 } // 另一种写法 function Rectangle() { this.base = Shape; this.base(); } // 子类继承父类的方法 Rectangle.prototype = Object.create(Shape.prototype); Rectangle.prototype.constructor = Rectangle; var rect = new Rectangle(); rect instanceof Rectangle // true rect instanceof Shape // true rect.move(1, 1) // 'Shape moved.'
上面程式碼表示,建構函式的繼承分成兩部分,一部分是子類別呼叫父類別的建構方法,另一部分是子類別的原型指向父類別的原型。
上面程式碼中,子類別是整體繼承父類別。有時,只需要單一方法的繼承,這時可以採用下面的寫法。
ClassB.prototype.print = function() { ClassA.prototype.print.call(this); // some code }
上面程式碼中,子類別B的print方法先呼叫父類別A的print方法,再部署自己的程式碼。這就等於繼承了父類別A的print方法。
__proto__屬性__proto__屬性指向目前物件的原型對象,即建構函數的prototype屬性。
var obj = new Object(); obj.__proto__ === Object.prototype // true obj.__proto__ === obj.constructor.prototype // true
上面程式碼首先新建了一個物件obj,它的__proto__屬性,指向建構函式(Object或obj.constructor)的prototype屬性。所以,兩者比較以後,回傳true。
因此,取得實例物件obj的原型對象,有三種方法。
obj.__proto__
#obj.constructor.prototype
Object.getPrototypeOf(obj)
上面三種方法之中,前兩種都不是很可靠。最新的ES6標準規定,__proto__屬性只有瀏覽器才需要部署,其他環境可以不部署。而obj.constructor.prototype在手動改變原型物件時,可能會失效。
var P = function () {}; var p = new P(); var C = function () {}; C.prototype = p; var c = new C(); c.constructor.prototype === p // false
上面程式碼中,C建構子的原型物件被改成了p,結果c.constructor.prototype就失真了。所以,改變原型物件時,一般要同時設定constructor屬性。
C.prototype = p; C.prototype.constructor = C; c.constructor.prototype === p // true
所以,建議使用第三種Object.getPrototypeOf方法,取得原型物件。該方法的用法如下。
var o = new Object(); Object.getPrototypeOf(o) === Object.prototype // true
可以使用Object.getPrototypeOf方法,檢查瀏覽器是否支援__proto__屬性,老式瀏覽器不支援這個屬性。
Object.getPrototypeOf({ __proto__: null }) === null
上面程式碼將一個物件的__proto__屬性設為null,然後使用Object.getPrototypeOf方法取得這個物件的原型,判斷是否等於null。如果目前環境支援__proto__屬性,兩者的比較結果應該是true。
有了__proto__屬性,就可以很方便得設定實例物件的原型了。假設有三個物件machine、vehicle和car,其中machine是vehicle的原型,vehicle又是car的原型,只要兩行程式碼就可以設定。
vehicle.__proto__ = machine; car.__proto__ = vehicle;
下面是一個實例,透過__proto__屬性與constructor.prototype屬性兩種方法,分別讀取定義在原型物件上的屬性。
Array.prototype.p = 'abc'; var a = new Array(); a.__proto__.p // abc a.constructor.prototype.p // abc
顯然,__proto__看起來更簡潔一些。
通过构造函数生成实例对象时,实例对象的__proto__属性自动指向构造函数的prototype对象。
var f = function (){}; var a = {}; f.prototype = a; var o = new f(); o.__proto__ === a // true
属性的继承属性分成两种。一种是对象自身的原生属性,另一种是继承自原型的继承属性。
对象的原生属性对象本身的所有属性,可以用Object.getOwnPropertyNames方法获得。
Object.getOwnPropertyNames(Date) // ["parse", "arguments", "UTC", "caller", "name", "prototype", "now", "length"]
对象本身的属性之中,有的是可以枚举的(enumerable),有的是不可以枚举的。只获取那些可以枚举的属性,使用Object.keys方法。
Object.keys(Date) // [] hasOwnProperty()
hasOwnProperty方法返回一个布尔值,用于判断某个属性定义在对象自身,还是定义在原型链上。
Date.hasOwnProperty('length') // true Date.hasOwnProperty('toString') // false
hasOwnProperty方法是JavaScript之中唯一一个处理对象属性时,不会遍历原型链的方法。
对象的继承属性用Object.create方法创造的对象,会继承所有原型对象的属性。
var proto = { p1: 123 }; var o = Object.create(proto); o.p1 // 123 o.hasOwnProperty("p1") // false
获取所有属性判断一个对象是否具有某个属性(不管是自身的还是继承的),使用in运算符。
"length" in Date // true "toString" in Date // true
获得对象的所有可枚举属性(不管是自身的还是继承的),可以使用for-in循环。
var o1 = {p1: 123}; var o2 = Object.create(o1,{ p2: { value: "abc", enumerable: true } }); for (p in o2) {console.info(p);} // p2 // p1
为了在for...in循环中获得对象自身的属性,可以采用hasOwnProperty方法判断一下。
for ( var name in object ) { if ( object.hasOwnProperty(name) ) { /* loop code */ } }
获得对象的所有属性(不管是自身的还是继承的,以及是否可枚举),可以使用下面的函数。
function inheritedPropertyNames(obj) { var props = {}; while(obj) { Object.getOwnPropertyNames(obj).forEach(function(p) { props[p] = true; }); obj = Object.getPrototypeOf(obj); } return Object.getOwnPropertyNames(props); }
用法如下:
inheritedPropertyNames(Date) // ["caller", "constructor", "toString", "UTC", "call", "parse", "prototype", "__defineSetter__", "__lookupSetter__", "length", "arguments", "bind", "__lookupGetter__", "isPrototypeOf", "toLocaleString", "propertyIsEnumerable", "valueOf", "apply", "__defineGetter__", "name", "now", "hasOwnProperty"]
对象的拷贝如果要拷贝一个对象,需要做到下面两件事情。
确保拷贝后的对象,与原对象具有同样的prototype原型对象。
确保拷贝后的对象,与原对象具有同样的属性。
下面就是根据上面两点,编写的对象拷贝的函数。
function copyObject(orig) { var copy = Object.create(Object.getPrototypeOf(orig)); copyOwnPropertiesFrom(copy, orig); return copy; } function copyOwnPropertiesFrom(target, source) { Object .getOwnPropertyNames(source) .forEach(function(propKey) { var desc = Object.getOwnPropertyDescriptor(source, propKey); Object.defineProperty(target, propKey, desc); }); return target; }
多重继承JavaScript不提供多重继承功能,即不允许一个对象同时继承多个对象。但是,可以通过变通方法,实现这个功能。
function M1(prop) { this.hello = prop; } function M2(prop) { this.world = prop; } function S(p1, p2) { this.base1 = M1; this.base1(p1); this.base2 = M2; this.base2(p2); } S.prototype = new M1(); var s = new S(111, 222); s.hello // 111 s.world // 222
上面代码中,子类S同时继承了父类M1和M2。当然,从继承链来看,S只有一个父类M1,但是由于在S的实例上,同时执行M1和M2的构造函数,所以它同时继承了这两个类的方法。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
以上是JavaScript程式中實作繼承特性的方式(圖文教學)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr

Node.js擅長於高效I/O,這在很大程度上要歸功於流。 流媒體匯總處理數據,避免內存過載 - 大型文件,網絡任務和實時應用程序的理想。將流與打字稿的類型安全結合起來創建POWE


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能