Js 對象之間的繼承及原型鏈查找分析

  • 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);

      [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-b5YjTJO9-1615779490405)(C:\Users\xiaomi\AppData\Roaming\Typora\typora-user-images\image-20210315112105641.png)]

      經過實例對象自己查找本身原型鏈的方法,這個方法繼承的是Person的方法,再查找new Person()的實例對象的原型對象,查找出它的方法。



Student函數部分的原型圖

在這裏插入圖片描述

完整的原型鏈查找:

    將Person對象的實例賦值給Student.prototype,因此s1指向的原型對象是Person對象。

    而Person的message()方法則存放在Person的原型對象中,因此s1在調用方法時,首先在自身的方法中查找,沒有查找到;繼續向原型查找,本身的原型上尚未找到方法;那麼原型方法又要在本身的原型上繼續查找,找到message()方法。

    若是還未找到,即Person的原型對象上仍是沒有該方法,則繼續想Person原型對象的原型對象查找,查找Object原型對象,若尚未,則查找錯誤。
在這裏插入圖片描述

相關文章
相關標籤/搜索