成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【JS基礎】對象繼承的定義與實現(xiàn)

darry / 1297人閱讀

簡介
類的概念,本身在javascript的語言上是不存在的, 但由于最近人們使用ES6語法,TS語言上都會有的class extends 繼承的概念, 下面我們需要使用原生js, 結合原型鏈,實現(xiàn)類的 繼承,多態(tài)
ES5實現(xiàn)繼承

原型繼承

借用構造函數(shù)繼承

mixin 復制繼承

寄生繼承

原型繼承方式

原型繼承, 主要利用對象的原型鏈 __proto__, 每一個對象都擁有__proto__, 它指向的是構造函數(shù)的prototype 原型對象.

一個對象的屬性或函數(shù)的尋找會經(jīng)歷以下幾個步驟。
以定義 var o = {};, 執(zhí)行 var toString = o.toString 為例.

執(zhí)行 var tmp = o,作為臨時引用 (為了描述使用)

嘗試檢查 tmp 是否自定義toString(),如果存在自定義屬性則立即執(zhí)行。如果當前對象無定義該屬性, 進入第3步

嘗試檢查 tmp 是否使用 Object.defineProperty 定義toString 的屬性描述, 如果存在定義,則直接引用,如果不存在則進入第4步

嘗試檢查 tmp 是否存在 __proto__,如果存在,則將tmp = o.__proto__, 執(zhí)行第2步; 如果不存在,則返回 undefined, 屬性查找結束;

具體案例

function Animal () {
  throw new Error("抽象類, 不允許直接實例化");
}
Animal.prototype.voice = function () {
  console.log("the " + this.name + " sound");
}

function Dog () {
  this.name = "dog";
}
Dog.prototype = Object.create(Animal.prototype);

// 顯示指向
Dog.prototype.constructor = Dog;

var dog = new Dog();

dog.voice(); // the dog sound
console.log(dog instanceof Dog);
console.log(dog instanceof Animal);

// 隱世指向 Animal.prototype.constructor
console.log(dog.__proto__.constructor === Animal);

優(yōu)點:

可以使用 instanceof 檢測是否是某一個父類

原型鏈實現(xiàn)方式

缺點:

無法借用父類構造函數(shù)

借用構造函數(shù)

// 模擬調用父類函數(shù)
Object.prototype.super = function (proto, name) {
  var args = Array.from(arguments).slice(1);
  var proto = proto.__proto__;
  while (proto && null == proto[name]) {
    proto = proto[name];
  }
  if (proto && typeof proto[name] === "function") {
    return proto[name].apply(this, args);
  }
  console.warn("the instance have not super " + name + " function");
};
function Animal (name) {
  this.name = name;
}

Animal.prototype.voice = function () {
  console.log(this.name + " sound");
};

function Dog (name, type) {
  Animal.apply(this, [name]);
  this.type = type;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Animal;

Dog.prototype.voice = function () {
  console.log("the dog type is " + this.type);
  this.super(Animal.prototype, "voice");
};

var dog = new Dog("二哈", "哈士奇");
dog.voice();
// the dog type is 哈士奇
// 二哈 sound

優(yōu)點:

能夠借用父類構造函數(shù)

具備鏈式調用函數(shù)

缺點:

子類構造函數(shù)需要調用父類構造函數(shù)

mixin復制繼承

依靠對象拷貝屬性的方式, 給予一個源對象未有的屬性賦值

function mixin(source, target) {
  for (var name in target) {
    if (!source[name]) {
      source[name] = target[name];
    }
  }
  return source;
}

var Animal = {
  name: "animal",
  voice: function () {
    console.log("the name is " , this.name);
    console.log("voice~~");
  }
};
var Cat = mixin({
  name: "cat",  
  sound: function () {
    return this.voice();
  }
}, Animal);

var helloKitty = mixin({
  name: "hello keitty"
}, Cat);

helloKitty.sound();

優(yōu)點:

實現(xiàn)簡單,只需要進行復制屬性和方法

缺點:

處理對象都為對象, 沒有處理構造函數(shù)

無法實現(xiàn)子類調用父類的場景

寄生繼承

寄生繼承屬于重寫, 新增父類創(chuàng)建的對象的屬性, 返回擴展的對象

function Animal() {
  this.speed = 10;
}

Animal.prototype.run = function () {
  console.log("speed is " + this.speed);
}

function Cat () {
  var animal = new Animal();
  var runFn = animal.run;

  animal.speed = 20;  
  animal.run = function () {
    console.log("the cat will run");
    runFn.apply(this, arguments);
  };
  return animal;
}
var cat = new Cat();
console.log(cat instanceof Cat);

優(yōu)點:

結合原型屬性和實例屬性實現(xiàn)方案

缺點:

無法共享屬性, 每一個新的對象都創(chuàng)建新的實例屬性和方法

Object.create

Object.create 是ES5定義的方法, 相比于字面量對象,構造函數(shù)對象, 又一種新的創(chuàng)建對象的方式。

var prototype = {foo: 1};
var o = Object.create(prototype);
console.log(o.foo); // 1
o.foo = 100;
console.log(o.foo); // 100
delete o.foo;
console.log(o.foo); // 1
console.log(o.__proto__ === prototype); // true

從上面可以看見, Object.create 傳入一個對象,同時會返回一個新的對象,而這個新的對象的__proto__指向傳入對象

Object.create(null)

返回一個無原型鏈的空對象, 對象的所有屬性均為實例屬性

Object.create 的 polyfill

// 簡化版 polyfill
Object.create = Object.create || function (proto) {
  function F() {}
  F.prototype = proto;
  return new F();
};
ES6 的 class extends

說完ES5的實現(xiàn)方式,我們來聊聊ES6自帶的語法。 classclass extends

ES6里的類

參照其它語言,如 java, 類中存在靜態(tài)屬性, 靜態(tài)方法, 實例屬性,實例方法.

聲明一個類

class Rectangle {
  // 類的構造函數(shù)
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}
let rect = new Reactangle(320, 240);
console.log(rect.height, rect.width);

注意: 類不存在聲明提前的概念,必須先定義后使用

使用 extends 創(chuàng)建子類
class Animal { 

  constructor(name) {
    // 實例屬性
    this.name = name;
  }
  // 原型屬性描述
  get fullname () {
    console.log(this.name);
  }

  // 原型方法
  speak() {
    console.log(this.name + " makes a noise.");
  }
}

// 靜態(tài)屬性
Animal.name = "Animal";

class Dog extends Animal {
  construcotr(name) {
    // 調用父類構造函數(shù)
    super(name);
  }
  speak() {
    console.log(this.name + " barks.");
  }
  // 靜態(tài)方法只適合創(chuàng)建工具函數(shù)
  // 返回 undefined
  static eat() {
    return this;
  }
}

var d = new Dog("Mitzie");
// "Mitzie barks."
d.speak();

實際上ES6的classclass extends 也是使用的原型鏈方式實現(xiàn)繼承關系。 super 是一個關鍵詞, 實際上是指向父類的prototype, 在constructor 使用super(), 可以調用父類的構造函數(shù), 使用super.method() 可以調用父類的原型方法。
原型屬性采用ES5的defineProperty定義屬性描述來實現(xiàn)。

小結

目前JS的使用場景越來越廣, 面向對象編程的使用也越來越多, 前端已經(jīng)Node.js都有需要用到類與繼承。 同時這也是多年來不變的前端JS考題。

相關知識推薦

Object.create

ES6 Class

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://systransis.cn/yun/94015.html

相關文章

  • 重溫JS基礎--繼承

    摘要:繼承了如上,我們通過方法借調了超類的構造函數(shù),實際上是在新創(chuàng)建的實力環(huán)境下調用了構造函數(shù)。組合繼承組合繼承的基本思想將原型鏈和借用構造函數(shù)的技術組合到一塊,從而發(fā)揮二者之長的一種繼承模式。繼承方法在上面這個例子中,構造函數(shù)定義了兩個屬性和。 在ECMAScript中只支持實現(xiàn)繼承,而且實現(xiàn)繼承主要是依靠原型鏈來實現(xiàn)的。 1. 什么是原型鏈 繼承基本思想:利用原型讓一個引用類型繼承另一個...

    sixleaves 評論0 收藏0
  • Js基礎知識(二) - 原型鏈繼承精彩講解

    摘要:有了原型鏈,就有了繼承,繼承就是一個對象像繼承遺產(chǎn)一樣繼承從它的構造函數(shù)中獲得一些屬性的訪問權。這里其實就是一個原型鏈與繼承的典型例子,開發(fā)中可能構造函數(shù)復雜一點,屬性定義的多一些,但是原理都是一樣的。 作用域、原型鏈、繼承與閉包詳解 注意:本章講的是在es6之前的原型鏈與繼承。es6引入了類的概念,只是在寫法上有所不同,原理是一樣的。 幾個面試常問的幾個問題,你是否知道 insta...

    mrcode 評論0 收藏0
  • Js基礎知識(二) - 原型鏈繼承精彩講解

    摘要:有了原型鏈,就有了繼承,繼承就是一個對象像繼承遺產(chǎn)一樣繼承從它的構造函數(shù)中獲得一些屬性的訪問權。這里其實就是一個原型鏈與繼承的典型例子,開發(fā)中可能構造函數(shù)復雜一點,屬性定義的多一些,但是原理都是一樣的。 作用域、原型鏈、繼承與閉包詳解 注意:本章講的是在es6之前的原型鏈與繼承。es6引入了類的概念,只是在寫法上有所不同,原理是一樣的。 幾個面試常問的幾個問題,你是否知道 insta...

    lingdududu 評論0 收藏0
  • ES6—class面向對象編程(8)

    摘要:接下來我們看下類的寫法,這個就很接近于傳統(tǒng)面向對象語言了。如果你想了解傳統(tǒng)面向對象語言,這里是一個好切入點。作為對象時,指向父類的原型對象。這些就是為將來在中支持面向對象的類機制而預留的。 在ES5中,我們經(jīng)常使用方法或者對象去模擬類的使用,并基于原型實現(xiàn)繼承,雖然可以實現(xiàn)功能,但是代碼并不優(yōu)雅,很多人還是傾向于用 class 來組織代碼,很多類庫、框架創(chuàng)造了自己的 API 來實現(xiàn) c...

    wangjuntytl 評論0 收藏0

發(fā)表評論

0條評論

darry

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<