1. 程式人生 > >Javascript 6 種繼承

Javascript 6 種繼承

1.原型鏈繼承

// 1.原型鏈繼承的兩個問題===》在借用建構函式中可以解決下下面的兩個問題
//problem: 在建立子型別的例項時,不能向超型別的例項傳遞引數(在這裡就是不能向A()裡傳遞引數)
function A(light) {
this.light1=light;
}
function B(light) {
this.light=light;
}
B.prototype=new A(); //在這裡就會引出屬性被其它例項共享的問題
var c=new B(123);
console.log(c.light);
console.log(c.light1);

// problem:屬性是引用型別的值時,修改引用型別後,繼承後會被所有例項共享
function C() {
this.color=["red","blue","pink"]
}
function D() {

}
D.prototype=new C();
var instance1=new D();
instance1.color.push("black")
var instance2=new D();
console.log(instance1);
console.log(instance2);

2.建構函式繼承

// 借用建構函式的兩個問題
// 1.方法屬性必須定義在借用建構函式之後,否則,重新定義的屬性會被超型別的屬性覆蓋
// 2.函式方法只能定義在建構函式中,沒有函式複用的說法了
function A(name) {
this.city="北京";
this.name=name;
this.countries=["美國","中國","英國"]
}
function B(name,age) {
this.city="上海";
A.call(this,name);
this.age=age;
// this.city="上海";應該寫在這裡
}
var s1=new B("bob",25);
console.log(s1);
s1.countries.push("india");
console.log(s1.city);

3.組合繼承

// 組合繼承(建構函式中定義屬性,原型物件中定義方法) 建立的例項會分別擁有自己的屬性 會使用相同的方法。
// 避免了原型鏈繼承與建構函式繼承的缺陷,宗旨,原型鏈繼承共享的屬性和方法,建構函式繼承例項屬性。
function superType(name) {
this.name = name;
this.colors = ["red", "blue"]
}
superType.prototype.sayName = function() {
console.log(this.name) //這裡的方法可以不用定義在建構函式中了
}

function subType(name, age) {
superType.call(this, name);
this.age = age;
}

// 繼承方法
subType.prototype = new superType();
subType.prototype.constructor = subType;
subType.prototype.sayAge = function() {
console.log(this.age)
}

var instance1 = new subType("jack", 10);
instance1.colors.push("black");
console.log(instance1.colors);
instance1.sayName();
instance1.sayAge();

var instance2 = new subType("tom", 20);
console.log(instance2.colors);
instance2.sayName();
instance2.sayAge();

 

4.原型式繼承

// 原型式繼承
// 1.problem:包含引用型別的屬性都會被共享
function object(o) {
function F() {}
F.prototype=o;
return new F();

}
var person={
name:"jack",
friends:["a","b","c"]
};
var anotherPerson= Object.create(person);
anotherPerson.name="tom";
anotherPerson.friends.push("d");

var otherPerson=Object.create(person,{
name:{
value:"gg" //2.Object.create的第二個引數會覆蓋原型物件上的同名屬性
}
})
console.log(anotherPerson.name);
console.log(otherPerson.name);

 

5.寄生式組合繼承

// 最完美的繼承,繼生式組合繼承
function superType(name) {
this.name1 = name;
this.colors = ["red", "blue"]
}
superType.prototype.sayName = function() {
console.log(this.name) //3.這裡的方法可以不用定義在建構函式中了,注意不要在原型物件中定義屬性
}

function subType(name, age) {
superType.call(this, name); //4.這裡的借用建構函式可以為每個例項建立一個屬性副本,建構函式superType只被呼叫一次,可以放在建構函式中
this.name = name;
this.age = age;
}

function inheritPrototype(subType,superTyper) {
var prototype=Object.create(superType.prototype); //5.Object.create 就相當於給被繼承的建構函式轉變為一個物件副本,避免superType被多次呼叫
prototype.constructor=subType;
subType.prototype=prototype;
}

inheritPrototype(subType,superType);

var instance1=new subType("張三"); //2.可以向超型別的屬性傳遞引數
console.log(instance1.name);
var instance2=new subType("張三");
console.log(instance2.name1);

instance1.colors.push("pink");//1.解決了引用型別值會被共享的問題
console.log(instance1.colors); 
console.log(instance2.colors);