繼承是面向對象的重要特徵。繼承是指子類對象擁有父類對象的屬性與方法,同時子類對象能夠覆蓋擴展父類對象的屬性和方法。函數
JS中繼承的特色:this
1.子類對象 擁有 父類對象 的 屬性和方法; (把構造函數稱爲一個類,使用構造函數爲當前對象初始化屬性)spa
2.子類對象能夠有本身的新屬性和方法;prototype
3.子類對象能夠重寫父類對象的方法;指針
4.JS中並無專門的繼承語法,但能夠經過原型鏈機制實現。對象
把共有的屬性封裝在父類,子類繼承繼承
繼承的優勢內存
1.提供了一種優良的代碼組合方式,提升了代碼的重用性。原型鏈
2.子類能夠靈活調用父類的屬性,同時能夠擴展覆蓋父類的屬性,體現靈活性。get
3.提供了代碼的可維護性
原型繼承方式:經過原型鏈完成繼承。任何對象都會經過原型鏈繼承Oject函數的 prototype對象中的屬性和方法
正常聲明兩個構造函數 ---人類 和學生
//人類 : 性別年齡-說話、跑跳
//人類中包括學生 --有學校 考試
//注意父類並非專門爲子類服務的,父類也會有相關的事例
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function(){
console.log("名字:" +this.name);
}
//建立學生構造函數
function Student( name ,age ,school){
this.name = name;
this.age = age;
this.school = school;
}
Student.prototype.gotoSchool=function(){
console.log("去"+this.school+"上學")
}
讓學生繼承人類的 sayhello( ) ;方法
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function(){
console.log("名字:" +this.name);
}
//建立學生構造函數
function Student( name ,age ,school){
this.name = name;
this.age = age;
this.school = school;
}
//修改了
Student.prototype = new Person(); //必須在添加方法前面
//new Person 沒有建立對象引用他,因此棧內存中沒有值
//Student的原型對象指針指向了 new Person 對象
Student.prototype.gotoSchool=function(){
console.log("去"+this.school+"上學");
}
//當前student1具有Person對象裏面屬性方法---任何Student實例具有 person裏的方法
var student1 = new Student("Shixin",18, "天津理工大學");
student1.gotoSchool();
student1.sayHello();
Person.prototype.category="哺乳類";
console.log(student1.category); //哺乳類
student1.category = "靈長類"; //
console.log(student1.category); //靈長類
var student2 = new Student("lis",20, "天津理工大學");
console.log(student2.category); //哺乳類
//添加設置,返回方法
Person.prototype.setCategory = function( val){
this.category = val;
}
person.prototype.getCategory = function(){
return this.category;
}
student1.setCategory("靈長類");
console.log(student1.getCategory()); ----------//靈長類
var student2 = new Student("lis",20, "天津理工大學");
console.log(student2.getCategory()); ----------------//哺乳類
缺點:
1.原型對象中數據發生變化,會致使多有對象數據都變化
2.沒法向父類·對象·傳遞參數。
3、構造函數繼承方式
經過構造函數完成繼承
缺點:只能繼承父類構造函數中執行的賦值的屬性,沒法對原型對象的屬性進行繼承,所以不多單獨使用
//構造函數的應用場景,只能繼承基本屬性,沒法繼承方法;
function Person( name,age){
this.name = name;
this.age = age;
}
//子類
function Student( name,age,schoolName){
this.schoolName = schoolName;
Person.call(this,name,age); //繼承基本屬性 ---賦值 name age
}
Student.prototype.goToSchool = function(){
console.log("去"+this.schoolName+"上學");
}
var st = new Student('張三',18,"理工大學");
st.goToSchool();
結果:----去理工大學上學
經過構造函數,原型鏈共同完成繼承,使用最多的方案
function Person( name,age){
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function(){
console.log("我叫"+this.name);
}
function Student ( name, age,schoolName){
this.schoolName = schoolName;
Person.call(this,name,age); //構造函數繼承方式--this值加到 建立的對象上,student
至關於進行了 this.name=name,this.age=age;
}
Student.prototype = new Person(); //重置原型鏈可使用Person()的方法
Student.prototype.gotoSchool = function(){
console.log("我去"+this.schoolName+"上學");
}
var student = new Student("張三",18,"理工大學");
student.sayHello();
student.gotoSchool();
我叫張三
我去理工大學上學
缺點: 調用兩次Person構造函數
1次-Student.prototype = new Person(); 只是原型鏈改變
2次-- Person.call(this,name,age);
爲了解決這個弊端採用下種方法
寄生組合繼承方式:將子對象的prototype 設定爲克隆出來的父類的 prototype 對象。最優的解決方案。
經過本身構建一個prototype --- 替換 Student.prototype = new Person();
Student.prototype = new Person(); // 只須要借用原型鏈不須要執行代碼
new person()的過程
1.建立內存空間
2.改變this指向
3.原型鏈指定
4.執行函數體
前3步須要,最後一步不須要
1. var ob = new Object();
2. ob.constructor = Student;
3 .ob.prototype = Person; 原型鏈指向Person
爲了避免打亂原型鏈 --提出一個公用方法
function inherit( parent, child){ //父親孩子
}
//寄生組合方式
function inherit( parent,child){ //建立一個深度克隆 父類 prototype對象 var prototype = Object( parent.prototype); //至關於又複製了一個內存空間 //改變這個protityoe對象的 構造指針constructor指針指向子類的構造函數。 prototype.constructor = child; //修改child的指針 child.prototype = prototype } function Person( name,age){ this.name = name; this.age = age; } Person.prototype.sayHello = function(){ Console.log("名字:" +this.name); } function Student(name,age,schoolName){ this.schoolName = schoolName; Person.call(this,name,age); } inherit(Person,Student); Student.prototype.gotoSchool = function(){ console.log("去" + this.schoolName +"上學"); }