原型、原型链和继承
一、原型 prototype 和 proto
- 每個對象都有一個__proto__屬性,并且指向它的prototype原型對象。
- 每個構造函數都有一個prototype原型對象 prototype原型對象里的constructor指向構造函數本身
prototype 和 __proto__有什么用呢?
實例對象的__proto__指向構造函數的prototype,從而實現繼承。(只有對象才有__proto__)
prototype對象相當于特定類型所有實例對象都可以訪問的公共容器。
二、原型鏈
var arr = [5,6,7]
arr.valueOf() // [5,6,7]
查找valueOf方法的過程當試圖訪問一個對象的屬性時,它不僅僅在該對象上搜尋,還會搜尋該對象的原型,以及該對象的原型的原型,依次層層向上搜索,直到找到一個名字匹配的屬性或到達原型鏈的末尾。查找valueOf大致流程當前實例對象obj,查找obj的屬性或方法,找到后返回沒有找到,通過obj. proto,找到obj構造函數的prototype并且查找上面的屬性和方法,找到后返回沒有找到,把Array.prototype當做obj,重復以上步驟當然不會一直找下去,原型鏈是有終點的,最后查找到Object.prototype時Object.prototype.proto === null,意味著查找結束.
arr.__proto__ === Array.prototype // true Array.prototype.__proto__ === Object.prototype //true arr.__proto__.__proto__ === Object.prototype // true// 原型鏈的終點 Object.prototype.__proto__ === null // true**原型鏈如下:
arr ---> Array.prototype ---> Object.prototype ---> null這就是傳說中的原型鏈,層層向上查找,最后還沒有就返回undefined
三、JavaScript 中的繼承
3.1 什么是繼承?
繼承是指一個對象直接使用另外一個對象的屬性和方法
由此可見只要實現屬性和方法的繼承,就達到繼承的效果
- 得到一個對象的屬性
- 得到一個對象的方法
3.2 屬性如何繼承?
我們先創建一個Person類
此時我想創建一個Teacher類,我希望它可以繼承Person所有的屬性,并且額外添加屬于自己特定的屬性;
一個新的屬性,subject——這個屬性包含了教師教授的學科。
定義Teacher的構造函數
function Teacher(name,age,subject){Person.call(this,name,age)this.subject = subject }屬性的繼承是通過再一個類內執行另一個類的構造函數,通過call指定this為當前執行環境,這樣就可以得到另一個類的所有屬性。
Person.call(this, name, age)實例化
var teacher = new Teacher('jack', 25, Math)teacher.age 25 teacher.name "jack"很明顯Teacher成功繼承了Person的屬性
3.3 方法如何繼承?
我們需要讓Teacher從Person的原型對象里繼承方法。我們要怎么做呢?我們都知道類的方法都定義在prototype里,那其實我們只需要把Person.prototype的備份賦值給Teacher.prototype即可Teacher.prototype = Object.create(Person.prototype) Object.create簡單說就是新建一個對象,使用現有的對象賦值給新建對象的__proto__可能有人會問為什么是備份呢?
因為如果直接賦值,那會是引用關系,意味著修改Teacher. prototype,也會同時修改Person.prototype,這是不合理的。另外注意一點就是,在給Teacher類添加方法時,應該在修改prototype以后,否則會被覆蓋掉,原因是賦值前后的屬性值是不同的對象。最后還有一個問題,我們都知道prototype里有個屬性constructor指向構造函數本身,但是因為我們是復制其他類的prototype,所以這個指向是不對的,需要更正一下。如果不修改,會導致我們類型判斷出錯
繼承方法的最終方案:
Teacher.prototype = Object.create(Person.prototype) Teacher.prototype.constructor = Teacher3.4 hasOwnProperty
在原型鏈上查詢屬性比較耗時,對性能有影響,試圖訪問不存在的屬性時會遍歷整個原型鏈。遍歷對象屬性時,每個可枚舉的屬性都會被枚舉出來。
要檢查是否具有自己定義的屬性,而不是原型鏈上的屬性,必須使用hasOwnProperty方法。
hasOwnProperty 是JavaScript 中唯一處理屬性并且不會
遍歷原型鏈的方法。
四、總結
prototype 和__proto__
每個對象都有一個__proro__屬性,并且指向它的prototype原型對象。
每個構造函數都有一個prototype原型對象,prototype原型對象里的constructor指向構造函數本身。
原型鏈
每個對象都有一個__proto__。它指向它的prototype原型對象,而prototype原型對象又具有一個自己的prototype對象,就這樣層層往上直到一個對象的prototype為 null.
這個查詢的路徑就是原型鏈。
JavaScript 中的繼承
- 屬性繼承
- 方法繼承
總結
- 上一篇: 煤矿三维可视化_三维激光扫描建模_BIM
- 下一篇: AD09 DXP保姆级教程系列——006