學習js繼承的6種方式

關於原型,原型鏈,構造函數和實例關係,能夠參考上一篇文章

地址:juejin.im/post/5cbfb3…

js 實現繼承的方式一:原型鏈繼承

function Father(){
    this.name = '父親';
}
Father.prototype.sayName = function(){
    console.log(this.name);
}
function Child(){}
Child.prototype = new Father();
var child1 = new Child();
child1.sayName();//父親
複製代碼

原型鏈繼承存在的問題

1.父類中的引用類型的屬性被全部子類共享; 2.子類不能向父類傳遞參數app

例子:函數

function Father(){
    this.names = ['kevi','jack'];
}
function Son(){
    
}
Son.prototype = new Father();
var son1 = new Son();
var son2 = new Son();
son1.names.push('jhs');
console.log(son1.names);//["kevi", "jack", "jhs"]
console.log(son2.names);//["kevi", "jack", "jhs"]
複製代碼

js 實現繼承的方式二:構造函數綁定法(借用構造函數法)

function Animal(job){
    this.species = '動物';
    this.ages = [1,2,3];//父類中存在引用類型的屬性
    this.job = job;
}
function Dog(name,color){
    this.name = name;
    this.color = color;
}
//怎麼樣才能使Dog繼承Animal呢?
//從新改寫Dog
function Dog(name,color,job){
    //Animal.apply(this,arguments);
    //或
    Animal.call(this,job);
    this.name = name;
    this.color =color;
}
let dog1 = new Dog('大毛','黑色','eat');
console.log(dog1.name);//大毛
console.log(dog1.species);//動物
console.log(dog1.job);//eat
dog1.ages.push(4);
console.log(dog1.ages);//[1,2,3,4]
let dog2 = new Dog('二毛','灰色');
console.log(dog2.ages);//[1,2,3]
複製代碼

構造函數綁定法的優缺點:

優勢: 1.避免了父類中的引用類型的屬性被全部子類共享的問題; 2.能夠向父類中傳參;post

缺點: 1.方法或屬性定義在構造函數中,不可以複用這些屬性或方法;(方法都在構造函數中定義,每次建立實例都會建立一遍方法。) 2.父類在原型中定義的方法對於子類不可見this

function Animal(){
    this.species = '動物';
    this.sayHello = function(){
        console.log('hello world');
    }
}
Animal.prototype.saySpecies = function(){
    console.log(this.species);
}
function Dog(name,color){
    this.name = name;
    this.color = color;
}
//怎麼樣才能使Dog繼承Animal呢?
//從新改寫Dog
function Dog(name,color){
    Animal.apply(this,arguments);
    //或
    //Animal.call(this);
    this.name = name;
    this.color =color;
}
const dog1 = new Dog('大毛','黑色');
console.log(dog1.name);//大毛
console.log(dog1.species);//動物
dog1.saySpecies();
複製代碼

js 實現繼承的方式三:組合繼承

function Parent(name){
    this.name = name;
    this.colors = ['yellow','red','black'];
}
Parent.prototype.sayName = function(){
    console.log(this.name);
}
function Child(name,age){
    Parent.call(this,name);
    this.age = age;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;

let child1 = new Child('kevin',12);
child1.colors.push('blue');
console.log(child1.name);//kevin
console.log(child1.age);//12
console.log(child1.colors);//['yellow','red','black','blue']
child1.sayName();//kevin

let child2 = new Child('jeck',11);
console.log(child2.name);//jeck
console.log(child2.age);//11
console.log(child2.colors);//['yellow','red','black']
child2.sayName();//jeck
複製代碼

組合繼承的優勢和缺點

優勢: 1.子類能夠向父類傳遞參數 2.父類中的引用類型的屬性不會被全部實例共享 3.父類原型中定義的方法能夠被子類繼承 4.能夠實現方法共享 5.是js實現繼承的最經常使用方法spa

缺點: 1.兩次調用父類構造函數; 一次是:Child.prototype = new Parent(); 另外一次是:執行 let child1 = new Child('kevin',12)時候,其實調用了Parent.call(this,name);prototype

js 實現繼承的方式四:原型式繼承

function createObj(o){
    function F(){}
    F.prototype = o;
    return new F();
}

var obj = {
    name:'kevin',
    colors:['red','blue','white']
}
var obj1 = createObj(obj);
var obj2 = createObj(obj);
console.log(obj1.name);//kevin
console.log(obj2.name);//kevin

obj1.name = 'kkk';
console.log(obj1.name);//kkk
console.log(obj2.name);//kevin

obj1.colors.push('green');
console.log(obj2.colors);//["red", "blue", "white", "green"]
//原型式繼承中的引用類型的屬性也會被共享,和原型鏈繼承類似
複製代碼

原型式繼承是Object.create()的模擬實現; Object.create(obj,[propertiesObject]); 接受兩個參數,第一個參數爲新建立對象的原型對象,第二個參數爲可選。若是沒有指定爲 undefined,則是要添加到新建立對象的可枚舉屬性(即其自身定義的屬性,而不是其原型鏈上的枚舉屬性)對象的屬性描述符以及相應的屬性名稱。這些屬性對應Object.defineProperties()的第二個參數3d

const friend = {
    name:'lili',
}
let f1 = Object.create(friend,{
    name :{
        value:'mimo'
    }
});
console.log(f1.name);
複製代碼

原型式繼承存在的缺點

1.原型式繼承中的引用類型的屬性也會被共享,和原型鏈繼承類似code

js 實現繼承的方式五:寄生式繼承

function createObj(o){
    var clone = Object.create(o);
    clone.sayName = function(){
        console.log('你正在使用寄生式繼承');
    }
    return clone;
}
var obj = {
    name:'lll'
}
var obj1 = createObj(obj);
obj1.sayName();//你正在使用寄生式繼承
複製代碼

寄生式繼承的缺點

1.經過使用寄生式繼承爲對象添加方法,不能實現方法的共享,這一點和借用構造函數方式一致cdn

js 實現繼承的方式六:寄生組合式繼承

咱們通常認爲組合繼承是最經常使用的繼承方式,不過組合繼承也有本身的不足之處,那就是兩次調用父類的構造函數,一次在建立子類原型的時候,一次在子類構造函數內部;寄生組合式繼承就是爲了下降調用父類構造函數開銷而出現的; 背後的原理就是:沒必要爲了指定子類型的原型而調用父類型的構造函數對象

function createObj(o){
    function F(){}
    F.prototype = o;
    return new F();
}
function prototype(child,parent){
    var prototype = createObj(parent.prototype);
    prototype.constructor = child;
    child.prototype = prototype;
}

//使用
prototype(child,parent);
複製代碼

//例子

function createObj(o){
        function F(){}
        F.prototype = o;
        return new F();
    };
    function prototype1(child,parent){
        var pro = createObj(parent.prototype);
        pro.constructor = child;
        child.prototype = pro;
    };
    function Parent1 (){
       this.name='kk';
       this.age = 12;
    };
    Parent1.prototype.say=function(){
         console.log(this.name);
      }
    function Child1(){
        Parent1.call(this);
        this.name='ll'
     }
    //使用
    prototype1(Child1,Parent1);
    var son = new child1();
    console.dir(son.say());//ll
複製代碼

寄生組合式繼承的優勢

1.只調用了一次父類的構造函數; 2.避免了在子類的原型上建立沒必要要的,多餘的屬性; 3.原型鏈保持不變,所以可以正常使用instanceof 和isPrototypeOf()

相關文章
相關標籤/搜索