1. 程式人生 > 其它 >javascript中物件的繼承方式

javascript中物件的繼承方式

技術標籤:JavaScript

1.建構函式繼承

function animal() {
  this.type = "動物"
}

function Cat(name, price) {
  animal.call(this, arguments)/*改變this指向*/
  this.name = name;
  this.price = price;
}

var cat1 = new Cat('tom', '$8888')
console.log('輸出繼承自建構函式animal的屬性type值', cat1.type)

2. 原型繼承

//prototype繼承
function Person() { this.type = "人類" } function Man(name, age) { this.name = name; this.age = age; } //一定要注意順序問題,就是繼承一定要在建立例項之前,這樣才能繼承到其相應的屬性 //錯誤寫法 // var per1 = new Man('ak', 21) // per1.prototype = new Person(); // per1.prototype.constructor = Man; // console.log(per1.type) //正確寫法 Man.prototype =
new Person(); Man.prototype.constructor = Man; var per1 = new Man('ak', 21); console.log(per1.type)

分析:

  • Man.prototype = new Person(); 的作用時將Man原型物件指向了Person的例項

  • Man.prototype.constructor = Man;
    該行程式碼的作用:
    1.由於每一個物件的原型prototype都有一個預設的constructor屬性,該屬性指向其建構函式;由於當我執行了原型繼承時,即Man.prototype = new Person();,那麼建構函式Man的原型便執行了Person

    2.從事便需要注意,Man的原型指向了Person,那麼之後建立的Man例項的prototype必然也是指向Person的,這樣便引起了原型繼承的錯亂關係,所以我們需要手動的將原型繼承手動改回來,改回其原本自身,即Man

3.非建構函式實現繼承

3.0 引入問題:

說明:
比如,現在有一個物件,叫做"中國人"

var Chinese = {
  nation: '中國',
  arr: [1, 2, 3]
}

還有一個物件,叫做"醫生"。

var Doctor = {
  career: '醫生'
}

請問怎樣才能讓"醫生"去繼承"中國人",也就是說,我怎樣才能生成一個"中國醫生"的物件?
這裡要注意,這兩個物件都是普通物件,不是建構函式,無法使用建構函式方法實現"繼承"。

3.1 淺拷貝實現繼承
  • 思路:把父物件的屬性,全部拷貝給子物件,也能實現繼承

淺拷貝繼承函式如下:

function extendCopy(f, c) {
  var c = {}
  for (let i in f) {
    c[i] = f[i]
  }
  return c;
}

  • 使用
var doctor3 = extendCopy(Chinese);
console.log(doctor3.nation)  //中國
console.log(doctor3.arr)  //[1,2,3]

使用淺拷貝的缺點:

  • 子已經繼承了父的所有屬性,但是當子繼承了父的引用型別的屬性時,
  • 實質上獲取到的是一個記憶體地址,因此會存在父物件被子物件撰改的心現象
  • extendCopy()只是拷貝基本型別的資料,我們把這種拷貝叫做"淺拷貝"
3.2 深拷貝實現繼承

說明:所謂深拷貝,就是能實現真正意義上對資料和物件的拷貝。
思路:使用遞迴呼叫

深拷貝函式如下:

//實現深拷貝
function deepCopy(f, c) {
  //
  var c = c || {}
  //將f拷貝至c
  for (let i in f) {
    //1.首先判斷是否為引用資料型別
    if (typeof f[i] === 'object') {
      //2。  陣列:[],物件:{})
      c[i] = (f[i].constructor === Array) ? [] : {};
      //遞迴呼叫(即判斷引用資料型別的子屬性是否仍然存在引用資料型別)
      deepCopy(f[i], c[i])
    } else {
      //當不是引用資料型別時,直接賦值拷貝
      c[i] = f[i]
    }
  }
  return c;
}

使用:

var doctor2 = deepCopy(Chinese);
doctor2.arr.push('5')
console.log('doctor2----', doctor2.arr);
console.log('Chinese----', Chinese.arr);

輸出結果:
在這裡插入圖片描述
說明:

  • 這時,父物件就不會受到影響了。