js的繼承方式(共6種):javascript
定義一個父級函數:
function Animal(name){ this.name = name; this.sleep = function(){ console.log(this.name+"在睡覺") } } Animal.prototype.eat = function(food){ console.log(this.name+"再吃"+food); }
第一種:原型鏈繼承(父類實例做爲子類的原型)java
function Cat(name){ this.name = name; } Cat.prototype.color = "白色"; Cat.prototype = new Animal(); var cat1 = new Cat("Tom"); // 實例1 var cat2 = new Cat("Jim"); // 實例2 var cat3 = new Cat("Sun"); // 實例3 console.log(cat1.name); console.log(cat1.color); // undefined console.log(cat2.sleep()); console.log(cat3.eat("fish")) 特色: 簡單易實現 父類實例的屬性和方法子類均可以繼承 缺點: 想要新增原型屬性和方法必須放在new Animal()語句以後 不能實現多繼承(一個子類同時繼承多個父類) 來自原型對象的屬性是全部實例共享的 建立子類實例時,沒法向父類構造函數傳參
第二種:構造函數繼承(經過使用call改變this指向,指向父類實例,至關於複製父類實例的屬性給子類)app
function Cat(name){ Animal.call(this); this.name = name; } var cat1 = new Cat("Tom"); console.log(cat1.name); console.log(cat1.sleep()); console.log(cat1.eat("fish")) // cat1.eat is not a function 特色: 能夠實現多繼承 建立子類實例時能夠向父類傳參 缺點: 只能繼承父類實例的屬性和方法,不能繼承原型的方法 函數不可複用 實例只是子類實例不是父類實例
第三種:實例繼承(爲父類實例添加新屬性,做爲子類實例返回)函數
function Cat(name){ console.log(this) var instance = new Animal(); instance.name = name; return instance; } var cat1 = new Cat("Tom"); var cat2 = Cat("Jim"); console.log(cat1.name) // Tom console.log(cat2.name) // Jim 特色: 不限制調用方式,new 構造函數 或者直接調用子類函數 獲得的都是一樣的結果 缺點: 不支持多繼承 實例是父類實例,不是子類的實例
第四種:拷貝繼承(獲取父類實例,經過循環父類實例,把父類實例的屬性和方法都賦給子類)this
function Cat(name){ var animal = new Animal(); for(var p in animal){ Cat.prototype[p] = animal[p]; } Cat.prototype.name = name; } var cat1 = new Cat("Jim"); var cat2 = new Cat("Jim"); console.log(cat1.name); console.log(cat2.eat("fish")); 特色: 能夠實現多繼承 缺點: 由於每次都要循環,形成內存消耗嚴重,效率低 不能夠枚舉的屬性方法就會獲取不到
第五種:組合繼承(經過調用父類的構造函數,繼承了父類的屬性和方法,並保留了傳參的優勢,經過將父類實例做爲子類的原型,實現了函數的複用)spa
function Cat(name){ Animal.call(this); this.name = name; } Cat.prototype = new Animal(); Cat.prototype.constructor = Cat; // console.log(Cat.prototype.constructor); var cat1 = new Cat("Tom"); var cat2 = new Cat("Li"); console.log(cat1.name); console.log(cat2.eat("apple")) 特色: 既能夠繼承實例的屬性和方法,也能夠繼承構造函數的屬性和方法 子類實例能夠給父類傳參 實例既是子類實例也是父類實例 函數可複用 缺點: 調用了兩次父類構造函數,生成了兩份實例 (1). 設置子類實例原型的時候 Cat.prototype = new Animal(); (2). 建立子類實例的時候 var cat1 = new Cat("Tom");
第六種:寄生組合繼承prototype
function Cat(name){ Animal.call(this); this.name = name; } (function(){ // 建立一個沒有實例方法的類 var Cate = function(){ } // 將父類原型當作這個類的原型 Cate.prototype = Animal.prototype; // 把實例做爲子類的原型 Cat.prototype = new Cate(); })() var cat1 = new Cat("Tom"); var cat2 = new Cat("Jim"); console.log(cat1); console.log(cat2.eat("apple")); 特色: 既能夠繼承實例的屬性和方法,也能夠繼承構造函數的屬性和方法 子類實例能夠給父類傳參 實例既是子類實例也是父類實例 能夠實現多繼承 函數可複用 經過寄生的方式,去掉了父類的實例屬性,調用兩次父類構造函數時不會初始化兩屬性和方法