摘要:原型繼承與類繼承類繼承是在子類型構造函數的內部調用父類型的構造函數原型式繼承是借助已有的對象創建新的對象,將子類的原型指向父類。
JavaScript 繼承方式的概念
js 中實現繼承有兩種常用方式:
原型鏈繼承(對象間的繼承) 類式繼承(構造函數間的繼承)
JavaScript不是真正的面向對象的語言,想實現繼承可以用JS的原型prototype機制或者call和apply方法
在面向對象的語言中,可以使用類來創建一個自定義對象,當然ES6中也引入了class來創建類。在這之前,我們需要使用js的原型來創建自定義對象。
原型繼承與類繼承類繼承是在子類型構造函數的內部調用父類型的構造函數
function Super (){ this.colors = ["blue","red"]; } function Sub () { Super.call(this); }
原型式繼承是借助已有的對象創建新的對象,將子類的原型指向父類。
function Super (id) { this.id = id; } Super.prototype.toString = function () { return "Super" + this.id; } function Sub (id) { this.id = id; } Sub.prototype = new Super(); // 這句即原型式繼承的核心代碼原型鏈繼承
為了讓子類繼承父類的屬性和方法,首先需要定義一個構造函數,然后將父類的實例賦值給構造函數的原型。
function Parent () { this.name = "Parent"; } function Child () { this.age = 10; } Chid.prototype = new Parent(); // Chid繼承Parent,形成原型鏈 var test = new Child(); console.log(test.name) // Parent console.log(test.age) // 10 得到被繼承的屬性 // 繼續原型鏈繼承 function Brother () { this.weight = 60; } Brother.prototype = new Child(); var peter = new Brother(); console.log(peter.name) //繼承了Child和Parent,輸出Parent console.log(peter.age) // 輸出10
所有的構造函數都繼承自Object,它是自動完成繼承的并不需要我們手動繼承,那么接著看它們的從屬關系
確定原型和實例的關系可以通過兩種方式確定原型和實例的關系,通過操作符instanceof和isPrototypeof()方法
console.log(peter instanceof Object); //true console.log(test instanceof Brother) //false,test是brother的父類 console.log(peter instanceof Child) //true console.log(peter instanceof Parent) //true
只要是原型鏈中出現過的原型,都可以說是改原型鏈派生的實例的原型。因此,isProtptypeof()方法也會返回true
在JS中,被繼承的函數成為父類(或者 基類、超類),繼承的函數成為子類(派生類)。使用原型繼承主要有兩個問題,一是字面量重寫原型會中斷關系,使用引用類型的原型,并且子類型無法給父類型傳遞參數。
偽類解決引用共享和超類型無法傳參的問題,我們可以采用"類式繼承"的方式
類式繼承(借用構造函數)function Parent (age) { this.colors = ["blue","red","green"]; this.age = age; } function Child (age) { Parent.call(this,age); } var peter = new Child(20); console.log(peter.age) //20 console.log(peter.colors) //blue,red,green peter.colors.push("white"); console.log(peter.colors) //blue,red,green,white
借用構造函數雖然解決了上面兩張問題,但沒有原型,所以我們需要原型鏈+借用構造函數的模式,這種模式成為組合繼承
組合繼承function Parent (age) { this.colors = ["blue","red","green"]; this.age = age; } Parent.prototype.run = function () { return this.colors + " is " +this.age; } function Child (age) { Parent.call(this,age); //對象冒充,給父類型傳參 } Child.prototype = new Parent(); //原型鏈繼承 var peter = new Child(20); console.log(peter.run()); //blue,red,green is 20
組合繼承是一種比較常用的方法,思路是使用原型鏈實現對原型屬性和方法的繼承,借用構造函數來實現對實例屬性的繼承。這樣,既實現了原型上定義方法的函數復用,又保證每個實例都有自己的屬性。
call()與apply()的用法:調用一個對象的一個方法,用另一個對象替換當前對象。
call(thisObj,Object); // call接收一個對象 apply(thisObj,[argArray]) //apply接收一個數組原型式繼承
這種繼承借助原型并基于已有的對象創建新的對象,同時還不用創建自定義類型的方式成為原型式繼承
function obj(o) { function F() {} F.prototype = o; return new F(); } var box = { name : "peter", arr : ["blue","red","green"] }; var b1 = obj(box); console.log(b1.name) // peter b1.name = "jack"; console.log(b1.name) //jack console.log(b1.arr) //blue,red,green b1.arr.push("white") //blue,red,green,white var b2 = obj(box); console.log(b2.name) // peter console.log(b1.arr) //blue,red,green
原型式繼承首先在obj()函數內部創建一個臨時性的構造函數,然后將傳入的對象作為這個構造函數的原型,最后返回這個臨時類型的新實例。
寄生式繼承這種繼承方式是把原型式+工廠模式結合起來,目的是為了封裝創建的過程。
function create(o){ var f = obj(o); f.run = function () { return this.arr;//同樣,會共享引用 }; return f; }組合式繼承的問題
組合式繼承是JS最常用的繼承模式,但組合繼承的父類型會在使用過程中被調用兩次,一次是創建子類型的時候,另一次是在子類型構造函數的內部
function Parent(name){ this.name = name; this.arr = ["哥哥","妹妹","父母"]; } Parent.prototype.run = function () { return this.name; }; function Child(name,age){ Parent.call(this,age);//第二次調用 this.age = age; } Child.prototype = new Parent();//第一次調用
以上代碼是組合繼承,那么寄生組合繼承解決了兩次調用的問題
寄生組合繼承function obj() { function F() {} F.prototype = o; return new F(); } function create(parent,test) { var f = obj(parent.prototype); //創建對象 f.constructor = test; //增強對象 } function Parent(name){ this.name = name; this.arr = ["brother","sister","parents"]; } Parent.prototype.run = function () { return this.name; }; function Child(name,age){ Parent.call(this,name); this.age =age; } inheritPrototype(Parent,Child); //通過這里實現繼承 var test = new Child("peter",20); test.arr.push("new"); console.log(test.arr); //brother,sister,parents,new console.log(test.run()); //只共享了方法 var test2 = new Child("jack",22); console.log(test2.arr); //引用問題解決call和apply
call和apply可以用來改變函數中this的指向:
// 定義一個全局函數 function f () { console.log(this.name); } // 定義一個全局變量 var name = "peter"; var obj = { name: "jack"; }; f.apply(window); //apple, 此時this 等于window 相當于window.f() f.apply(obj); //jack, 此時this === obj 相當于obj.f()
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79043.html
摘要:可以通過構造函數和原型的方式模擬實現類的功能。原型式繼承與類式繼承類式繼承是在子類型構造函數的內部調用超類型的構造函數。寄生式繼承這種繼承方式是把原型式工廠模式結合起來,目的是為了封裝創建的過程。 js繼承的概念 js里常用的如下兩種繼承方式: 原型鏈繼承(對象間的繼承) 類式繼承(構造函數間的繼承) 由于js不像java那樣是真正面向對象的語言,js是基于對象的,它沒有類的概念。...
摘要:理解的函數基礎要搞好深入淺出原型使用原型模型,雖然這經常被當作缺點提及,但是只要善于運用,其實基于原型的繼承模型比傳統的類繼承還要強大。中文指南基本操作指南二繼續熟悉的幾對方法,包括,,。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。 怎樣使用 this 因為本人屬于偽前端,因此文中只看懂了 8 成左右,希望能夠給大家帶來幫助....(據說是阿里的前端妹子寫的) this 的值到底...
摘要:當然這還沒完,因為我們還有重要的一步沒完成,沒錯就是上面的第行代碼,如果沒有這行代碼實例中的指針是指向構造函數的,這樣顯然是不對的,因為正常情況下應該指向它的構造函數,因此我們需要手動更改使重新指向對象。 第一節內容:javaScript原型及原型鏈詳解(二) 第一節中我們介紹了javascript中的原型和原型鏈,這一節我們來講利用原型和原型鏈我們可以做些什么。 普通對象的繼承 ...
摘要:當這步完成,這個對象就與構造函數再無聯系,這個時候即使構造函數再加任何成員,都不再影響已經實例化的對象了。此時,對象具有了和屬性,同時具有了構造函數的原型對象的所有成員,當然,此時該原型對象是沒有成員的。 前言 本篇文章用來記錄下最近研究對象的一些心得,做一個記錄與總結,以加深自己的印象,同時,希望也能給正在學習中的你一點啟發。本文適合有一定JavaScript基礎的童鞋閱讀。原文戳這...
閱讀 3382·2021-11-22 13:53
閱讀 3422·2021-10-11 11:11
閱讀 937·2019-08-30 14:12
閱讀 1227·2019-08-29 17:16
閱讀 647·2019-08-29 16:45
閱讀 3359·2019-08-29 12:56
閱讀 676·2019-08-28 17:55
閱讀 2071·2019-08-26 13:24