1、原型的概念
原型定義: 每個函數都會建立一個prototype屬性,這個屬性是一個對象,包含應該有特定引用類型的執行個體共享的屬性和方法。同時呢,這個prototype屬性對象又是調用構造函數建立的對象的原型。
原型的特點是: 在原型上定義的屬性和方法可以被對象執行個體共享。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI2EzX4xSZz91ZsAzNfRHLGZkRGZkRfJ3bs92YsAjMfVmepNHLRtkc1g2TJZTQClGVF5UMR9Fd4VGdsATNfd3bkFGazxycykFaKdkYzZUbapXNXlleSdVY2pESa9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL2EWM2ImNzcjZiVmYiBTM4Y2M2QjM2UmYiV2YzMmZwgzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
意思就是,在構造函數Person的原型屬性寫方法和屬性,可以被new Person生成的執行個體共享。
深入了解原型的本質:
隻要建立函數,函數就會有一個prototype屬性(指向原型對象),同時,原型對象會有一個constructor屬性(指向與之關聯的構造函數)。
在定義構造函數時,原型對象預設隻會獲得constructor屬性,其他所有方法都繼承自Object。
構造函數執行個體 :由調用構造函數建立的對象稱為執行個體對象,該執行個體内部[[Prototype]]指針會被指派為構造函數的原型。浏覽器裡以_proto_屬性表現。
!!!注意: 執行個體與構造函數原型直接有直接的關系,但執行個體與構造函數之間沒有直接關系(執行個體對象是由構造函數建立的)。
構造函數、執行個體與原型三者的關系:
Object.create()可以建立一個新對象,同時傳入的對象參數為其原型。
2、繼承的概念
寄生式組合繼承:
首先回顧下組合繼承:
function Super(name) {
this.name = name;
this.colors = ["red", "blue"];
}
Super.prototype.sayName = function() {
console.log(this.name);
}
function Sub(name, age) {
//這裡開始盜用構造函數
Super.call(this, name);
this.age = age;
}
Sub.prototype = new Super();
Sub.prototype.constructor = Sub;
Sub.protype.sayAge = function() {
console.log(this.age);
}
組合式繼承會有缺陷:會出現兩組同樣的父類屬性,一個在sub原型上,一個在sub執行個體上。不信?你可以:
let person1 = new Sub()
分析一下。原因在于super調用了兩次。
寄生式組合繼承通過盜用構造函數繼承屬性,但使用混合式原型鍊繼承方法。思路為:不通過調用父類構造函數給子類原型指派,而是取得父類原型的一個副本。
寄生式組合繼承的基本模式:
原理主要是:把Sub的原型為Super的執行個體,即sub.prototype.prototype=super.prototype
function inherit(sub, super){
let prototype = object(super.prototype);
prototype.constructor = sub;
sub.prototype = prototype;
}
将Sub.prototype = new Super(); => inherit(sub, super);即可。