js繼承方式講解

蘆夢宇發表於2018-05-26

類分為 私有屬性 公有屬性 靜態方法

使用物件方式,繼承公有屬性

let obj2 = {
   age: 9,
   name:'jw'
};
let obj = {
  name:'zfpx',
  getPName(){ // 可以通過super關鍵字獲取到父屬性
    return super.name
  },
  __proto__:obj2
}
console.log(obj.getPName());
複製程式碼

只繼承公有屬性

Child.prototype.__proto__ = Parent.prototype;
複製程式碼
Object.setPrototypeOf(Child.prototype, Parent.prototype)
複製程式碼

上面兩個等價,一個是es5一個是es6

js繼承方式講解

只繼承共有屬性

Child.prototype = Object.create(Parent.prototype,{constructor:{value:Child}});
let child = new Child;
child.smoking();
console.log(child.constructor);
複製程式碼

實現原理:

function create(parentPrototype,props){
  function Fn() {}
  Fn.prototype = parentPrototype;
  let fn = new Fn();
  for(let key in props){
    Object.defineProperty(fn, key, {
      ...props[key],
      enumerable:true  //不加這句列舉不出來child.constructor(undefined)
    });
  }
  return fn;
}
// defineProperty中加了set get就不能加 writable和value了。
Child.prototype = create(Parent.prototype,{constructor:{value:Child}});
let child = new Child();
console.log(child.constructor);
複製程式碼

js繼承方式講解

只繼承私有屬性 再子類中呼叫父類的方法即可 Parent.call(this)

function Parent(){
    this.parent = 'parent';
}
Parent.prototype.smoking = function () {
    console.log('吸菸')
}
function Child(){
    Parent.call(this)
}
console.log(new Child().parent)
複製程式碼

child繼承父類的所有的屬性

function Parent(){
    this.parent = 'parent';
}
Parent.prototype.smoking = function () {
    console.log('吸菸')
}
function Child(){}
 Child.prototype = new Parent;
let child = new Child();
Child.prototype.eat = function () {
 console.log('吃')
 }
 console.log(child.parent)
 console.log(child.smoking)
 child.__proto__.eat();
 console.log(child.__proto__=== Child.prototype)
 console.log(Child.prototype.constructor === Child)
複製程式碼

為了追本溯源, 我順便研究了new運算子具體幹了什麼?發現其實很簡單,就幹了三件事情.

var obj  = {};
obj.__proto__ = F.prototype;
F.call(obj);
複製程式碼

第一行,我們建立了一個空物件obj;

第二行,我們將這個空物件的proto成員指向了F函式物件prototype成員物件;

第三行,我們將F函式物件的this指標替換成obj,然後再呼叫F函式.

我們可以這麼理解: 以 new 操作符呼叫建構函式的時候,函式內部實際上發生以下變化:

1、建立一個空物件,並且 this 變數引用該物件,同時還繼承了該函式的原型。

2、屬性和方法被加入到 this 引用的物件中。

3、新建立的物件由 this 所引用,並且最後隱式的返回 this

function Otaku (name, age) {
    this.name = name;
    this.age = age;

    this.habit = 'Games';
}

Otaku.prototype.strength = 60;

Otaku.prototype.sayYourName = function () {
    console.log('I am ' + this.name);
}

// 模擬new
function objectFactory() {

    var obj = new Object(),

    Constructor = [].shift.call(arguments);

    obj.__proto__ = Constructor.prototype;

    var ret = Constructor.apply(obj, arguments);//對返回指值做處理,如果是引用物件則返回物件,如果是基本型別則忽略返回值,依然返回物件obj

    return typeof ret === 'object' ? ret : obj;

};

var person = objectFactory(Otaku, 'Kevin', '18')

console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) // 60

person.sayYourName(); // I am Kevin
複製程式碼

es6中的class繼承公有屬性和私有屬性和靜態方法

class Child extends Parent{ // 要求繼承父親的私有和有公有
  constructor(){
    super(); // Parent.call(this);
    this.age = 9; // 私有屬性
  }
  static a(){ // 屬於類上的方法
    return 1;
  }
  smoking(){ // 原型上的方法
    console.log('smoking')
  }
}
let child = new Child();
複製程式碼

相關文章