物件導向(ES5與ES6類的繼承解析)
物件導向的語言都有一個類的概念,通過類可以建立多個具有相同方法和屬性的物件,ES6之前並沒有類的概念,在ES6中引入類class.
ES5 物件導向
建立物件(四種模式簡介,此外還有動態原型模式、寄生建構函式模式、穩妥建構函式模式等)
一、工廠模式
function createPerson (Name,Age,Job) {
var man= new Object();
man.name= Name;
man.age= Age;
man.job= Job;
man.sayName= function () {
alert(this.name)
}
return man;
}
var personOne= createPerson ("Erric",26,"Engineer");
var personTwo= createPerson ("Lori",26,"teacher");
優點:解決了多個相似物件的建立問題
缺點: ① 物件識別問題無法解決(即怎麼知道一個物件的型別)
二、建構函式模式
function Person (Name,Age,Job) {
this.name = Name;
this.age = Age;
this.job= Job;
this.sayName= function () {
alert(this.name)
}
}
var personOne= new Person("Erric",26,"Engineer");
var personTwo= new Person("Lori",26,"teacher");
注一: 若不使用new操作符直接呼叫函式,那麼其屬性和方法都會被新增到window物件裡面(因為在全域性作用域呼叫一個方法時,this總是指向window物件)
如: Person("Erric",26,"Enginee")
window.sayName() // 彈出 "Erric"
window.name // "Erric"
window.age // 26
注二: new 操作符實際上進行了以下操作
① 建立一個新的物件
② 將建構函式的作用域賦給新物件(this指向了這個新的物件)
③ 執行建構函式中的程式碼(為這個新物件新增屬性)
④ 返回這個新的物件
優點:① 不用顯式的建立物件
② 將屬性和方法賦給了this物件
③ 沒有return語句
缺點:① 每個方法都要在每個例項上重新建立一遍(personOne和personTwo中的sayName方法不是同一個方法,每個函式都是一個物件,故每 定義了一個函式就例項化了一個物件)。
此問題也可以通過將方法單獨抽出來解決(但是方法一多,都移到全域性的話封裝性就無從談起),如下:
function Person (Name,Age,Job) {
this.name = Name;
this.age = Age;
this.job= Job;
this.sayName= sayName
}
function sayName() {
alert(this.name)
}
var personOne= new Person("Erric",26,"Engineer");
var personTwo= new Person("Lori",26,"teacher");
② 若是將公共的sayName方法移到全域性,那麼又沒有封裝性可言了。
三、原型模式
function Person () {
}
Person.prototype.name= "Erric"
Person.prototype.age= "28"
Person.prototype.job= "Job"
Person.prototype.sayName= function () {
alert(this.sayName)
}
優點:① 解決了函式共用的問題,不用每個例項都建立一遍方法。
缺點:① 不能傳參
② 如果例項中修改了原型中的屬性(引用型別)或方法,那麼這個屬性或方法會被徹底的修改,而影響到其他例項。
四、建構函式+原型組合模式
function Person (Name,Age,Job) {
this.name= Name
this.age= Age
this.job= Job
}
Person.prototype.sayName= function () {
alert(this.name)
}
// 上面往原型上新增屬性和方法的也可如下寫,但是此時原型的constructor不指向Person建構函式,而是指向Object,因為Person.prototype就像一個新的物件例項,它的__proto__指向Object原型。
// Person.prototype= {
constructor: Person, // 重新再例項中定義constructor的指向,覆蓋Object原型中的constructor指向
sayName: function () {
alert(this.name)
}
}
var personOne= new Person("Erric",26,"Engineer");
var personTwo= new Person("Lori",26,"teacher");
原型物件的理解(重要)
1.首先得明白以下三點:
① 每個函式(含建構函式)都有一個prototype屬性,指向Person原型
② 每個例項都有一個__proto__屬性,也指向Person原型
③ 每個原型都有一個constructor屬性,指向其對應的建構函式
建構函式、例項、原型三者關係如下圖:
2.萬物皆物件,說明原型鏈的最開始點都是Object,所以任何一個引用型別的 instanceof Object都會返回true。
類的繼承(兩種方式)
一、原型鏈繼承
對於什麼是原型鏈?
每個建構函式都有一個原型物件,原型物件的constructor指向這個建構函式本身,而例項的__proto__屬性又指向原型物件。這個假設一個例項的__proto__內部指標指向其原型,而它的原型又是另一個型別的例項,那麼它的原型又將指向另一個原型,另一個原型也包含一個指向它的建構函式的指標,假設另一個原型又是另一個型別的例項,這樣層層遞進,就構成了例項與原型的鏈條,這就是原型鏈的基本概念。
實現原型鏈的繼承方式基本如下:
function Father () {
this.appearance = "beautiful"
}
Father.prototype.sayHappy = function () {
alert("快樂")
}
function Child () {
this.name= "Jhon"
}
Child.prototype= new Father() // 繼承了父類的方法和屬性
Child.prototype.addArr= [1,2,3,4,5]
var child= new Child()
child.sayHappy() // 彈出“快樂”
child.appearance // "beautiful"
child.addArr // [1,2,3,4,5]
原型鏈繼承的缺點:① 不能傳參 ② 若原型上的方法時引用型別的話,不小心被修改了的話會影響其他例項。
二、藉助建構函式繼承(利用calll和apply改變this指標)
基本思路:在子型別建構函式的內部呼叫超型別的建構函式。
function Father (Hobby){
this.hobby= Hobby
}
Father.prototype.sayHappy = function () {
alert("快樂")
}
function Child () {
this.name= "Jhon"
Father.call(this,"Play Games") // 或者Father.apply(this,["Play Games"]),繼承了Father的屬性和方法
}
var child = new Child()
child.sayHappy // 沒有反應,原型上的方法和屬性不會繼承
child.hobby // "Play Games"
藉助建構函式繼承的缺點:① 方法都在建構函式中定義,函式的複用無從談起 ② 超類中的方法對子類不可見。
三、組合繼承(也叫經典繼承,將原型鏈和藉助建構函式繼承相結合)
思路:1.原型鏈實現對原型屬性和方法的繼承;
2.建構函式實現對例項屬性的繼承,且呼叫基類的建構函式;
function Father(Hobby) {
this.hobby= Hobby;
this.exGF = ['cuihua', 'erya']
}
Father.prototype.sayHappy = function () {
alert("快樂")
}
function Child () {
this.name= "Jhon"
Father.call(this,"Play Games") // 或者Father.apply(this,["Play Games"]),繼承了Father的屬性和方法
}
Child.prototype= new Father()
Student.prototype.sayName= function () {
alert(this.name);
}
var liHua= new Child()
liHua.sayHappy()
liHua.sayName()
檢測物件屬性的兩種方法:
object.hasOwnProperty(屬性名),這個方法檢測的是物件例項的屬性(若是返回true),不能檢測原型上的屬性。
in操作符,檢測物件所有的屬性,包含原型和例項上的額,有的話就返回true.
判斷一個原型是否在某個例項的原型鏈上:
Person.prototype.isPropotypeOf(personOne) // true
Object.prototype.isPropotypeOf(personOne) // true
判斷一個建構函式是否在例項的原型鏈中出現過:
personOne instanceof Person // true
personOne instanceof Object // true
ES6 物件導向
ES6中引入了Class(類)這個概念,通過關鍵字class可以建立一個類。類的資料型別就是函式,類的所有方法都定義在prototype屬性上。
class Person () {
constructor (x,y) {
this.name= x
this.age= y
}
sayName () {
alert("快樂")
}
}
var liHua= new Person("張俊澤",26)
注: 可以理解為constuctor中的屬性和方法為ES5中的建構函式部分,和constructor同級的是ES5中原型上的方法和屬性。
ES6的繼承通過extends關鍵字實現
class Father(){}
class Child extends Father {
constructor(x,y,color){
super(x,y)
this.color= color
}
toString() {
retunr "世界和平!"
}
}
上面程式碼中,constructor方法和toString方法之中,都出現了super關鍵字,它在這裡表示父類的建構函式,用來新建父類的this物件。
子類必須在constructor方法中呼叫super方法,否則新建例項時會報錯。這是因為子類沒有自己的this物件,而是繼承父類的this物件,然後對其進行加工。如果不呼叫super方法,子類就得不到this物件。
類的prototype和__proto__屬性
Class作為建構函式的語法唐,同時有prototype和__proto__屬性,因此存在兩條繼承鏈:
① 子類的__proto__,表示建構函式的繼承,總是指向父類
② 子類的prototype屬性的__proto__屬性,表示方法的繼承,總是指向父類的prototype屬性。
class Father {
}
class Child extends Father{
constructor () {
super()
}
}
var childOne= new Child()
Child.__proto__ == Father // true
childOne.__proto__ == Child.prototype // true
Child.prototype.__proto__ == Fahter.prototype // true
相關文章
- ES6與ES5繼承的解析繼承
- 【JavaScript】ES5/ES6 建立物件與繼承JavaScript物件繼承
- Javascript物件導向與繼承JavaScript物件繼承
- es5繼承和es6類和繼承繼承
- 物件導向:繼承物件繼承
- 物件導向--繼承物件繼承
- 物件導向-繼承物件繼承
- ES5和ES6的類的繼承繼承
- Golang物件導向_繼承Golang物件繼承
- java物件導向繼承Java物件繼承
- 物件導向之繼承物件繼承
- php物件導向--繼承PHP物件繼承
- Effective C++:物件導向與繼承C++物件繼承
- JS的物件導向(理解物件,原型,原型鏈,繼承,類)JS物件原型繼承
- ES6中的類繼承和ES5中的繼承模式詳解繼承模式
- 物件導向之_繼承概念物件繼承
- es6繼承 vs js原生繼承(es5)繼承JS
- es5建構函式,es6類和類的繼承函式繼承
- ES6 - 類與繼承繼承
- JavaScript物件導向—繼承的實現JavaScript物件繼承
- 物件導向:類的定義和繼承的幾種方式物件繼承
- Javascript實現物件導向繼承JavaScript物件繼承
- 21. 物件導向之繼承物件繼承
- javascript的物件導向的繼承實現JavaScript物件繼承
- Kotlin 物件導向程式設計 (OOP) 基礎:類、物件與繼承詳解Kotlin物件程式設計OOP繼承
- 物件導向 -- 三大特性之繼承 補充 抽象類 介面類物件繼承抽象
- JS繼承es5和es6JS繼承
- 物件導向 -- 三大特性之繼承物件繼承
- 說清楚javascript物件導向、原型、繼承JavaScript物件原型繼承
- JavaScript物件導向 ~ 原型和繼承(1)JavaScript物件原型繼承
- 5-Java物件導向-繼承(下)Java物件繼承
- 《JavaScript物件導向精要》之五:繼承JavaScript物件繼承
- java學習——物件導向之繼承Java物件繼承
- php物件導向多繼承實現PHP物件繼承
- JavaScript物件導向那些東西-繼承JavaScript物件繼承
- JAVA物件導向高階一:繼承Java物件繼承
- ES6繼承和ES5繼承是完全一樣的麼?繼承
- python物件導向的繼承-組合-02Python物件繼承