欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JS中常見的8種繼承方法總結(jié)

 更新時間:2023年10月17日 15:17:19   作者:酥脆角  
這篇文章主要給大家介紹了關(guān)于JS中常見的8種繼承方法,在js中所有的引用類型都繼承了Object,而繼承也是通過原型鏈實現(xiàn)的,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

1. 原型鏈繼承:

原型鏈繼承是JavaScript中最基本的繼承方式。每個對象都有一個原型對象,通過原型鏈將屬性和方法沿著對象鏈傳遞下來。在原型鏈繼承中,通過將子構(gòu)造函數(shù)的原型對象指向父構(gòu)造函數(shù)的實例,實現(xiàn)了繼承。這意味著子對象可以訪問父對象原型鏈上的屬性和方法。

function Parent() {
  this.name = 'Parent';
}
Parent.prototype.sayHello = function() {
  console.log('Hello');
};

function Child() {
  this.name = 'Child';
}
Child.prototype = new Parent();

var child = new Child();
child.sayHello(); // Hello
function Parent() {
  this.name = 'Parent';
}
Parent.prototype.sayHello = function() {
  console.log('Hello');
};

function Child() {
  this.name = 'Child';
}
Child.prototype = new Parent();

var child = new Child();
child.sayHello(); // Hello

在這個例子中,Child對象的原型對象被設(shè)置為Parent的一個實例。這樣,當(dāng)我們調(diào)用child.sayHello()時,它會首先在子對象上查找sayHello方法,然后在父對象原型鏈上找到并執(zhí)行該方法。注意:原型鏈繼承的缺點是,所有子對象共享同一個原型對象,對原型對象的修改會影響到所有子對象。

2. 構(gòu)造函數(shù)繼承(經(jīng)典繼承):

構(gòu)造函數(shù)繼承是通過在子構(gòu)造函數(shù)中調(diào)用父構(gòu)造函數(shù)來實現(xiàn)繼承。在構(gòu)造函數(shù)繼承中,通過在子構(gòu)造函數(shù)中使用**call()apply()**方法,將父構(gòu)造函數(shù)的上下文設(shè)置為子對象的上下文,從而實現(xiàn)繼承。

function Parent(name) {
  this.name = name;
}

function Child(name) {
  Parent.call(this, name);
}

var child = new Child('Child');
console.log(child.name); // Child
function Parent(name) {
  this.name = name;
}

function Child(name) {
  Parent.call(this, name);
}

var child = new Child('Child');
console.log(child.name); // Child

在這個例子中,我們通過在Child構(gòu)造函數(shù)內(nèi)部調(diào)用Parent構(gòu)造函數(shù),并傳遞子對象特定的參數(shù),實現(xiàn)了繼承。注意:構(gòu)造函數(shù)繼承只能繼承父構(gòu)造函數(shù)的實例屬性,無法繼承父構(gòu)造函數(shù)的原型對象上的方法。

3. 組合繼承:

組合繼承結(jié)合了原型鏈繼承和構(gòu)造函數(shù)繼承,既繼承了父構(gòu)造函數(shù)的屬性,又繼承了父構(gòu)造函數(shù)原型對象上的方法。在組合繼承中,通過調(diào)用父構(gòu)造函數(shù)的方式實現(xiàn)屬性的繼承,通過將子構(gòu)造函數(shù)的原型對象指向父構(gòu)造函數(shù)的實例實現(xiàn)方法的繼承。

function Parent(name) {
  this.name = name;
}
Parent.prototype.sayHello = function() {
  console.log('Hello');
};

function Child(name) {
  Parent.call(this, name);
}
Child.prototype = new Parent();

var child = new Child('Child');
child.sayHello(); // Hello
function Parent(name) {
  this.name = name;
}
Parent.prototype.sayHello = function() {
  console.log('Hello');
};

function Child(name) {
  Parent.call(this, name);
}
Child.prototype = new Parent();

var child = new Child('Child');
child.sayHello(); // Hello

在這個例子中,我們通過調(diào)用**Parent.call(this, name)來繼承父構(gòu)造函數(shù)的屬性,并通過Child.prototype = new Parent()**將子構(gòu)造函數(shù)的原型對象指向父構(gòu)造函數(shù)的實例,從而實現(xiàn)方法的繼承。組合繼承的優(yōu)點是既能夠繼承父構(gòu)造函數(shù)的屬性,又能夠繼承父構(gòu)造函數(shù)原型對象上的方法。然而,缺點是在創(chuàng)建子對象時會調(diào)用兩次父構(gòu)造函數(shù),一次是在設(shè)置原型時,一次是在創(chuàng)建子對象時。這樣會產(chǎn)生一些不必要的開銷。

4. 原型式繼承:

原型式繼承是通過使用一個臨時構(gòu)造函數(shù)和**Object.create()**方法來實現(xiàn)繼承。

var parent = {
  name: 'Parent',
  sayHello: function() {
    console.log('Hello');
  }
};

var child = Object.create(parent);
console.log(child.name); // Parent
child.sayHello(); // Hello
var parent = {
  name: 'Parent',
  sayHello: function() {
    console.log('Hello');
  }
};

var child = Object.create(parent);
console.log(child.name); // Parent
child.sayHello(); // Hello

在這個例子中,我們創(chuàng)建了一個parent對象,然后使用**Object.create()**方法創(chuàng)建了一個新對象child,并將其原型對象指向parent對象,實現(xiàn)了繼承。原型式繼承的本質(zhì)是創(chuàng)建一個新對象,將其原型對象指向另一個已有的對象。這種方式可以實現(xiàn)屬性和方法的繼承,但是不能傳遞構(gòu)造函數(shù)的參數(shù)。

5. Object.create()

Object.create() 是把現(xiàn)有對象的屬性,掛到新建對象的原型上,新建對象為空對象

ECMAScript 5通過增加Object.create()方法將原型式繼承的概念規(guī)范化了。這個方法接收兩個參數(shù):作為新對象原型的對象,以及給新對象定義額外屬性的對象(第二個可選)。在只有一個參數(shù)時,Object.create()與這里的函數(shù)A方法效果相同。

let person = {
  name: 'mjy',
  age: 19,
  hoby: ['唱', '跳'],
  showName() {
    console.log('my name is: ', this.name)
  }
}
 
let child1 = Object.create(person)
child1.name = 'xxt'
child1.hoby.push('rap')
let child2 = Object.create(person)
 
console.log(child1)
console.log(child2)
console.log(person.hoby) // ['唱', '跳', 'rap']let person = {
  name: 'mjy',
  age: 19,
  hoby: ['唱', '跳'],
  showName() {
    console.log('my name is: ', this.name)
  }
}
 
let child1 = Object.create(person)
child1.name = 'xxt'
child1.hoby.push('rap')
let child2 = Object.create(person)
 
console.log(child1)
console.log(child2)
console.log(person.hoby) // ['唱', '跳', 'rap']

優(yōu)點: 不需要單獨創(chuàng)建構(gòu)造函數(shù)。

缺點: 屬性中包含的引用值始終會在相關(guān)對象間共享,子類實例不能向父類傳參

6. 寄生式繼承

寄生式繼承的思路與(寄生) 原型式繼承 和 工廠模式 似, 即創(chuàng)建一個僅用于封裝繼承過程的函數(shù),該函數(shù)在內(nèi)部以某種方式來增強對象,最后再像真的是它做了所有工作一樣返回對象。

function objectCopy(obj) {
  function Fun() { };
  Fun.prototype = obj;
  return new Fun();
}
 
function createAnother(obj) {
  let clone = objectCopy(obj);
  clone.showName = function () {
    console.log('my name is:', this.name);
  };
  return clone;
}
 
let person = {
     name: "mjy",
     age: 18,
     hoby: ['唱', '跳']
}
 
let child1 = createAnother(person);
child1.hoby.push("rap");
console.log(child1.hoby); // ['唱', '跳', 'rap']
child1.showName(); // my name is: mjy
 
let child2 = createAnother(person);
console.log(child2.hoby); // ['唱', '跳', 'rap']function objectCopy(obj) {
  function Fun() { };
  Fun.prototype = obj;
  return new Fun();
}
 
function createAnother(obj) {
  let clone = objectCopy(obj);
  clone.showName = function () {
    console.log('my name is:', this.name);
  };
  return clone;
}
 
let person = {
     name: "mjy",
     age: 18,
     hoby: ['唱', '跳']
}
 
let child1 = createAnother(person);
child1.hoby.push("rap");
console.log(child1.hoby); // ['唱', '跳', 'rap']
child1.showName(); // my name is: mjy
 
let child2 = createAnother(person);
console.log(child2.hoby); // ['唱', '跳', 'rap']

優(yōu)點: 寫法簡單,不需要單獨創(chuàng)建構(gòu)造函數(shù)。

缺點: 通過寄生式繼承給對象添加函數(shù)會導(dǎo)致函數(shù)難以重用。使用寄生式繼承來為對象添加函數(shù), 會由于不能做到函數(shù)復(fù)用而降低效率;這一點與構(gòu)造函數(shù)模式類似.

7. 寄生組合式繼承

前面講過,組合繼承是常用的經(jīng)典繼承模式,不過,組合繼承最大的問題就是無論什么情況下,都會調(diào)用兩次父類構(gòu)造函數(shù);一次是在創(chuàng)建子類型的時候,一次是在子類型的構(gòu)造函數(shù)內(nèi)部。寄生組合繼承就是為了降低父類構(gòu)造函數(shù)的開銷而實現(xiàn)的。

通過借用構(gòu)造函數(shù)來繼承屬性,通過原型鏈的混成形式來繼承方法。本質(zhì)上,就是使用寄生式繼承來繼承超類型的原型,然后再將結(jié)果指定給子類型的原型。

function objectCopy(obj) {
  function Fun() { };
  Fun.prototype = obj;
  return new Fun();
}
 
function inheritPrototype(child, parent) {
  let prototype = objectCopy(parent.prototype);
  prototype.constructor = child;
  Child.prototype = prototype;
}
 
function Parent(name) {
  this.name = name;
  this.hoby = ['唱', '跳']
}
 
Parent.prototype.showName = function () {
  console.log('my name is:', this.name);
}
 
function Child(name, age) {
  Parent.call(this, name);
  this.age = age;
}
 
inheritPrototype(Child, Parent);
Child.prototype.showAge = function () {
  console.log('my age is:', this.age);
}
 
let child1 = new Child("mjy", 18);
child1.showAge(); // 18
child1.showName(); // mjy
child1.hoby.push("rap");
console.log(child1.hoby); // ['唱', '跳', 'rap']
 
let child2 = new Child("yl", 18);
child2.showAge(); // 18
child2.showName(); // yl
console.log(child2.hoby); // ['唱', '跳']function objectCopy(obj) {
  function Fun() { };
  Fun.prototype = obj;
  return new Fun();
}
 
function inheritPrototype(child, parent) {
  let prototype = objectCopy(parent.prototype);
  prototype.constructor = child;
  Child.prototype = prototype;
}
 
function Parent(name) {
  this.name = name;
  this.hoby = ['唱', '跳']
}
 
Parent.prototype.showName = function () {
  console.log('my name is:', this.name);
}
 
function Child(name, age) {
  Parent.call(this, name);
  this.age = age;
}
 
inheritPrototype(Child, Parent);
Child.prototype.showAge = function () {
  console.log('my age is:', this.age);
}
 
let child1 = new Child("mjy", 18);
child1.showAge(); // 18
child1.showName(); // mjy
child1.hoby.push("rap");
console.log(child1.hoby); // ['唱', '跳', 'rap']
 
let child2 = new Child("yl", 18);
child2.showAge(); // 18
child2.showName(); // yl
console.log(child2.hoby); // ['唱', '跳']

優(yōu)點: 高效率只調(diào)用一次父構(gòu)造函數(shù),并且因此避免了在子原型上面創(chuàng)建不必要,多余的屬性。與此同時,原型鏈還能保持不變;

缺點: 代碼復(fù)雜

8. ES6類繼承:

在ES6中引入了類的概念,通過class關(guān)鍵字和extends關(guān)鍵字可以實現(xiàn)類的繼承。

class Parent {
  constructor(name) {
    this.name = name;
  }

  sayHello() {
    console.log('Hello');
  }
}

class Child extends Parent {
  constructor(name) {
    super(name);
  }
}

const child = new Child('Child');
console.log(child.name); // Child
child.sayHello(); // Hello
class Parent {
  constructor(name) {
    this.name = name;
  }

  sayHello() {
    console.log('Hello');
  }
}

class Child extends Parent {
  constructor(name) {
    super(name);
  }
}

const child = new Child('Child');
console.log(child.name); // Child
child.sayHello(); // Hello

在這個例子中,我們定義了一個Parent類,通過extends關(guān)鍵字實現(xiàn)子類Child對父類Parent的繼承。子類使用super關(guān)鍵字調(diào)用父類的構(gòu)造函數(shù),并可以訪問父類的屬性和方法。ES6類繼承提供了更加語法簡潔和面向?qū)ο蟮睦^承方式。

以上是JavaScript中常見的八種繼承方式,每種方式都有其特點和適用場景。根據(jù)具體需求,你可以選擇適合的繼承方式來構(gòu)建對象之間的關(guān)系。

總結(jié)

到此這篇關(guān)于JS中常見的8種繼承方法的文章就介紹到這了,更多相關(guān)JS繼承方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論