js中的繼承

構造函數(shù)繼承

  • 繼承:子類繼承父類所有屬性和行為,父類不受影響。
  • 目的:找到類之間的共性精簡代碼
//構造函數(shù)繼承只能繼承對象內(nèi)部方法
function Person(name){
    this.name = name;
    this.eyes = "兩只";
    this.legs = "兩條";
}
function Student(name){
    Person.call(this,name);
   // Person.apply(this,[name]);
  //  Person.bind(this)(name);
    this.className = "二班";
}
let newPerson = new Student("張三");
console.log(newPerson.className);

為了實現(xiàn)原型的繼承可以使用原型的賦值

  • 但是簡單原型繼承,出現(xiàn)影響父類的情況;
function Dad(height){
    this.name = "張三";
    this.age = 20;
    this.height = height;
    this.money = "$1000000";
}
Dad.prototype.hobby = function(){
    console.log("喜歡高爾夫");
}

function Son(height){
    Dad.call(this,height);
    // Dad.apply(this,[height])
    // Dad.bind(this)(height);
}
Son.prototype = Dad.prototype  //直接賦值
Son.prototype.hobby = function(){
    console.log("籃球");
}
let newSon = new Son("178cm");
// console.log(newSon);
newSon.hobby(); // 籃球
let newDad = new Dad("179cm");
newDad.hobby(); //籃球
//輸出兩個都是顯示籃球,父類方法被覆蓋了繼承方法不可靠
  • 組合繼承 修改子類原型的指向,添加一個構造函數(shù)做為媒介
  function Dad(){
      this.name = "張三";
  }
  Dad.prototype.hobby = function(){
      console.log("高爾夫");
  }
  function Son(){
      Dad.call(this);
  }
  let F = function(){}
  F.prototype = Dad.prototype;
  Son.prototype = new F(); // 新開辟內(nèi)存地址
  Son.prototype.constructor = Son;
  Son.prototype.hobby = function(){
    console.log("籃球");
};
let newSon = new Son("178cm");
// console.log(newSon);
newSon.hobby(); // 籃球
let newDad = new Dad("179cm");
newDad.hobby(); //高爾夫

原型的深拷貝繼承

  • 傳值和傳址問題

    • 基本數(shù)據(jù)類型:Number、String、Boolean、Null、Undefined 拷貝不存在傳值問題
    • 復雜數(shù)據(jù)類型/引用數(shù)據(jù)類型:Array、Date、Math、RegExp、Object、Function等存在拷貝傳值問題
   let a = 10;
    let b = a;
    b = 20;
    console.log(a); // 10  b 改版沒有影響a 的值
    let obj = {
        name: "張三",
        age: 20,
        arr: [1, 2, 3],
        obj3: {
        },
        test: undefined,
        fn: function () {
            console.log("fn...");
        },
        test2: null
    }
  let obj2 = obj;
    obj2.age = 30;
    console.log(obj); /*{name: "張三", age: 30, arr: Array(3), obj3: {…}, test: undefined, …}
age: 30
arr: (3) [1, 2, 3]
fn: ? ()
name: "張三"
obj3: {}
test: undefined
test2: null
__proto__: Object*/
// 結果顯示obj 屬性age被修改了
  • 采用JSON序列化拷貝對象
let obj2 = JSON.parse(JSON.stringify(obj));
obj2.age = 30;
console.log(obj2); 
/*{name: "張三", age: 30, arr: Array(3), obj3: {…}, test2: null}
age: 30
arr: (3) [1, 2, 3]
name: "張三"
obj3: {}
test2: null
__proto__: Object*/
console.log(obj); /* {name: "張三", age: 20, arr: Array(3), obj3: {…}, test: undefined, …}
age: 20
arr: (3) [1, 2, 3]
fn: ? ()
name: "張三"
obj3: {}
test: undefined
test2: null
__proto__: Object*/

-JOSN序列化的不足

如果拷貝對象包含函數(shù),或者undefined等值,此方法就會出現(xiàn)問題
  • 淺拷貝和深拷貝
  //遞歸深拷貝
  function deepCopy(obj){
      let newObj = Array.isArray(obj)?[]:{};
      for(let key in obj){
          if(obj.hasOwnProperty(key)){
              if(typeof obj[key] == "object"){
                  newObj[key] = deepCopy(obj[key]);
              }else{
                  newObj[key] = obj[key];
              }
          }
      }
      return newObj;
  }
 let obj2 = deepCopy(obj);
    console.log(obj2);/*{name: "張三", age: 20, arr: Array(3), obj3: {…}, test: undefined, …}
age: 20
arr: (3) [1, 2, 3]
fn: ? ()
name: "張三"
obj3: {}
test: undefined
test2: null
__proto__: Object*/拷貝成功
  • 深拷貝繼承
 function Dad(){
     this.name = "張三";
 }
 Dad.prototype.hobby = function(){
     console.log("高爾夫");
 }
 function Son(){
     Dad.call(this);
 }
 Son.prototype = deepCopy(Dad.prototype); // 新開辟內(nèi)存地址
 Son.prototype.constructor = Son;
 Son.prototype.hobby = function(){
console.log("籃球");
};
let newSon = new Son("178cm");
newSon.hobby(); // 籃球
let newDad = new Dad("179cm");
newDad.hobby(); //高爾夫

原型的繼承

  • 原型鏈是指對象在訪問屬性或方法時的查找方式。

1.當訪問一個對象的屬性或方法時,會先在對象自身上查找屬性或方法是否存在,如果存在就使用對象自身的屬性或方法。如果不存在就去創(chuàng)建對象的構造函數(shù)的原型對象中查找 ,依此類推,直到找到為止。如果到頂層對象中還找不到,則返回 undefined。

2.原型鏈最頂層為 Object 構造函數(shù)的 prototype 原型對象,給 Object.prototype 添加屬性或方法可以被除 null 和 undefined 之外的所有數(shù)據(jù)類型對象使用。

  function Drag(){
    this.ele = "some value..."
  }
 Drag.prototype.ele = "prototype value....";
let drag1 = new Drag();
console.log(drag1.ele); // 輸出some value...


 function Drag(){
   // this.ele = "some value..."
  }
 Drag.prototype.ele = "prototype value....";
let drag1 = new Drag();
console.log(drag1.ele); // 輸出 prototype value....


 function Drag(){
   // this.ele = "some value..."
  }
// Drag.prototype.ele = "prototype value....";
Object.prototype.ele = 'Object.value...';
let drag1 = new Drag();
console.log(drag1.ele); // 輸出 Object.value...

ES6中的類

  • 類的寫法
class Person{
    height="178cm";
    constructor(name,age){
        //屬性
        this.name = name;
        this.age = age;
    }
    //方法
    getName(){
        console.log("姓名是:"+this.name);
    }
}
let student = new Person("張三",20);
student.getName();
  • 靜態(tài)方法和屬性:實例不會繼承的屬性和方法

    class Person{
        //靜態(tài)方法
        static hobby(){
            console.log("喜歡籃球");
        }
    }
    //靜態(tài)屬性
    Person.height = "178cm";
    //通過類來調(diào)用
    Person.hobby();
    console.log(Person.height);
    
  • 類的繼承:extends

    class Dad{
        name = "張三";
        age = 40;
        constructor(height){
            this.height = height;
        }
        hobby(){
            console.log("喜歡籃球");
        }
    }
    class Son extends Dad{
        constructor(height){
            //表示父類的構造函數(shù)
            super(height);
        }
    }
    let son1 = new Son("178cm");
    son1.hobby();
    console.log(son1.height);
    

包裝對象

  • 除過null,undefined,基本類型都有自己對應的包裝對象:String Number Boolean
  • 包裝對象把所有的屬性和方法給了基本類型,然后包裝對象消失

常用方法

  • hasOwnProperty():看是不是對象自身底下的屬性
  • contructor查看對象的構造函數(shù) 可以用來做判斷
  • instanceof:對象與構造函數(shù)是否在原型鏈上有關系
  • toString()判斷類型; 轉(zhuǎn)換字符串 進制轉(zhuǎn)換
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 選擇一種繼承方式 JavaScript 是一門動態(tài)語言,動態(tài)意味著高靈活性,而這尤其可以體現(xiàn)在繼承上面。JavaS...
    George_Wm閱讀 1,621評論 0 0
  • 前言 ES6之前,沒有嚴格意義上的class繼承, 其實JS(ES5)主要是依靠原型鏈來實現(xiàn)繼承的。 既然要實現(xiàn)繼...
    Mica_馬超閱讀 1,012評論 0 2
  • 面向?qū)ο蟮恼Z言支持兩種繼承方式,接口繼承和實現(xiàn)繼承js無法實現(xiàn)接口繼承,只支持實現(xiàn)繼承,主要通過原型鏈來實現(xiàn)。具體...
    jadefan閱讀 168評論 0 2
  • 方式一、原型鏈繼承 分析: 這種方式實現(xiàn)的本質(zhì)是通過將子類的原型指向了父類的實例,子類的實例就可以通過proto訪...
    tency小七閱讀 334評論 0 0
  • # 概述 本文主要記錄js中實現(xiàn)繼承的幾種方法的實現(xiàn),優(yōu)缺點分析 # 知識鋪墊 + **構造函數(shù),原型和實例的關系...
    HLE閱讀 711評論 0 0

友情鏈接更多精彩內(nèi)容