Js 對象之間的繼承javascript
構造函數的屬性繼承java
①對象拷貝 :使用for....in循環繼承父對象屬性函數
<script> var student1 = { name : "lisi", id : 1213, meaasge : function(){ console.log(name + "," + id); } }; //使用for....in循環繼承父對象屬性 //封裝成一個函數 function student(parent,child){ for (var k in parent) { if (child[k]) { continue;//對於student2裏獨有的要保留的值,則跳過該次循環 } child[k] = parent[k]; } } student(student1,student2); console.log(student2); </script>
上述繼承父對象是對象拷貝,實際上繼承指的是類型和類型之間的繼承,而封裝的構造函數就是用來建立類對象的this
②原型繼承prototype
//原型繼承 function Person(name, age, sex, score) { this.name = name; this.age = age; this.sex = sex; } //抽象,提取全部的公共屬性,放到一個父類型中 function Student(score){ this.score = score; } function Teacher(course){ this.crouse = crouse; } //原型對象,能夠將本身的屬性和方法繼承給未來的實例對象使用 Student.prototype = new Person("li",21,"male"); //生成一個實例 var s1 = new Student(90); console.dir(s1);
原型繼承,在沒有修改constructor以前,Student是沒有本身的constructor屬性的,但它有繼承Person對象是的constructor屬性,它指向的是Person。因此,這裏須要人爲定義一個constructor屬性,指向Student。3d
//原型對象,能夠將本身的屬性和方法繼承給未來的實例對象使用 Student.prototype = new Person("li",21,"male"); Studnet.prototype.constructor = Student; //生成一個實例 var s1 = new Student(90); console.dir(s1); console.log(s1.constructor);
這種繼承的缺點是,只能繼承一次,不適用屬性的繼承。code
③函數的 call 方法對象
//函數的 call 方法 function fn(a,b){ console.log(this);//指向的是window console.log(a+b); } var name = { name:"li" }; //普通函數的調用fn(1,1) //call方法 第一個參數用來指定this,第二個及之後傳的是實參。 fn.call(name,3,3);
函數call ,函數自己就是一種對象,能夠有本身的屬性和方法。call方法自己就是一種指向函數的方法。blog
call方法 在調用函數的時候,有兩個功能:①更改函數內部的this指向;②調用函數執行內部代碼,其當調用時,第一個參數用來指定this,第二個及之後傳的是實參。繼承
④借用構造函數繼承屬性
直接對父類型的構造函數進行一個普通調用,在調用的過程當中,內部的this指向的是window,經過call方法更改Person內部的this指向調用函數(如,student調用的,使用call方法後,this指向的是student)
//借用構造函數繼承屬性 function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; } //抽象,提取因此的公共屬性,放到一個父類型中 function Student(name,age,sex,score){ //對父類型進行一個普通調用 Person.call(this,name,age,sex); this.score = score; } function Teacher(name,age,sex,course){ Person.call(this,name,age,sex) this.crouse = crouse; } var s2 = new Student("li",22,"male",90); console.dir(s2);
構造函數的方法的繼承
for...in繼承、原型繼承、
①for...in繼承
//構造函數的方法繼承 function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; } //抽象,提取全部的公共屬性,放到一個父類型中 Person.prototype.message = function(){ console.log(123); } function Student(name,age,sex,score){ Person.call(this,name,age,sex); this.score = score; } function Teacher(name,age,sex,course){ Person.call(this,name,age,sex) this.crouse = crouse; } //for ..in繼承 for(var k in Person.prototype){ //Student保留本身的constructor 不讓Studnet繼承Person的constructor if(k == "constructor"){ continue; } Student.prototype[k] = Person.prototype[k]; }
②原型繼承
//原型繼承 Student.prototype = new Person(); //在繼承的狀況下也不能改變Student的constructor的指向 Student.prototype.constructor = Student; var s1 = new Student("li",21,"male",91); s1.message(); console.dir(s1);
③組合繼承:屬性在構造函數內部繼承,方法經過原型繼承
//構造函數的方法繼承 function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; } //抽象,提取全部的公共屬性,放到一個父類型中 Person.prototype.message = function(){ console.log(123); } function Student(name,age,sex,score){ //屬性的繼承,使用call方法繼承 Person.call(this,name,age,sex); this.score = score; } function Teacher(name,age,sex,course){ Person.call(this,name,age,sex) this.crouse = crouse; } //方法繼承,經過原型繼承 Student.prototype = new Person(); //在繼承的狀況下也不能改變Student的constructor的指向 Student.prototype.constructor = Student; var s1 = new Student("li",21,"male",91); s1.message(); console.dir(s1);
經過實例對象自己查找本身原型鏈的方法,這個方法繼承的是Person的方法,再查找new Person()的實例對象的原型對象,查找出它的方法。
將Person對象的實例賦值給Student.prototype,因此s1指向的原型對象是Person對象。
而Person的message()方法則存放在Person的原型對象中,因此s1在調用方法時,首先在自身的方法中查找,沒有查找到;繼續向原型查找,本身的原型上尚未找到方法;那麼原型方法又要在本身的原型上繼續查找,找到message()方法。
若是還未找到,即Person的原型對象上仍是沒有該方法,則繼續想Person原型對象的原型對象查找,查找Object原型對象,若尚未,則查找錯誤。