// 一、構造函數
function Person(name) {
this.name = name;
};
// 二、Es6 class
class Person2 {
constructor(name) {
this.name = name;
};
};
複製代碼
// 實例化
console.log(new Person('張三'), new Person2('李四'));
複製代碼
function Parent1() {
this.name = 'parent1';
};
Parent1.prototype.say = function() { // 沒法被Child1的實例對象繼承
console.log('say hello!');
};
function Child1() {
Parent1.call(this); // 改變this指向
this.type = 'child1';
};
console.log(new Child1());
複製代碼
PS:缺點是隻能繼承構造函數中的屬性和方法,沒法繼續原型對象上的屬性和方法,如圖: bash
function Parent2() {
this.name = 'parent2';
};
Parent2.prototype.say = function() {
console.log('say hello parent2!');
};
function Child2() {
this.type = 'child2';
};
Child2.prototype = new Parent2();
console.log(new Child2()) // new Child2()_proto_===Child2.prototype
複製代碼
繼承的原理:new Child2()實例對象的_proto屬性指向的是構造函數Child2的prototype原型對象,
即 new Child2()_proto_===Child2.prototype;
因爲Child2.prototype = new Parent2(),
則可經過 new Parent2()的_proto_屬性找到Parent2的prototype原型對象。
複製代碼
PS:缺點是經過一個構造函數實例多個對象時候,修改構造函數的屬性,全部的繼承自構造函數的實例對象的改屬性都將改變。以下所示:函數
function Parent2() {
this.name = 'parent2';
this.arr1 = [1,2,3,4];
this.arr2 = [1,2,3,4];
};
function Child2() {
this.type = 'child2';
};
Child2.prototype = new Parent2();
var obj1 = new Child2();
var obj2 = new Child2();
obj1.arr1.push(5) // 因爲obj自己並無arr1屬性,則經過_proto_原型鏈找到了Parent2的arr2屬性
obj1.arr2 = [1,2,3,4,5] // 這種方式並不會修改obj2.arr2屬性,至關於給obj1新增長了arr2屬性。
console.log(obj1, obj2)
複製代碼
PS:從圖中能夠看到
obj1.arr1.push(5)
修改使得
obj2.arr1
的值也被修改。這顯然不是咱們想要的,咱們但願各個實例之間是相互獨立的。
function Parent3() {
this.name = 'parent3';
this.arr1 = [1,2,3,4];
};
Parent3.prototype.say = function() {
console.log('say hello!')
}
function Child3() {
Parent3.call(this); // 改變了this指向,使得Parent3中的this指向的是Child3的實例對象。
this.type = 'child3';
};
Child3.prototype = new Parent3()
var o3 = new Child3();
var o4 = new Child3();
o3.arr1.push(5)
console.log(o3, o4)
複製代碼
PS: 能夠看到這裏已經解決了方法一、2中的問題。可是這裏有個問題就是
Parent3
構造函數被執行了兩次。
Parent3.call(this); // 改變了this指向,使得Parent3中的this指向的是Child3的實例對象。
Child3.prototype = new Parent3() // 既然上面已經繼承了Parent3構造函數中的屬性,這裏只是爲了繼承Parent3原型屬性
思考:根據以前原型鏈的相關知識,有如下關係
new Parent3().__proto__ === Parent3.prototype
故這裏能夠改爲:
Child3.prototype = Parent3.prototype // 缺點Child3和Parent3的constructor是同一個
複製代碼
var o3 = new Child3(); // 這裏o3實例應該是由`Child3`直接生成的實例。
更具根據以前原型鏈的相關知識
o3 instanceof Child3 // true
o3 instanceof Parent3 // true
instanceof判斷o3是Child3原型鏈上的一個實例若是想要直接判斷o3是Child3直接生成的實例,能夠經過constructor:
咱們指望
o3.constructor === Child3
三實際上的結果:
o3.constructor === Parent3
複製代碼
// 代碼優化
function Parent4() {
this.name = 'parent4';
this.arr1 = [1,2,3,4];
};
function Child4() {
Parent3.call(this);
this.type = 'child4';
};
Child4.prototype = Object.create(Parent4.prototype); // Object.create建立的對象只是_proto_的引用
Child4.prototype.constructor = Child4 // 給Child4原型對象添加constructor,覆蓋_proto_的constructor
var o5 = new Child4();
var o6 = new Child4();
o5.arr1.push(5)
console.log(o5, o6)
複製代碼
instanceo
和constructor
的使用。