首頁  >  文章  >  web前端  >  JavaScript OOP 概念:基於類別與基於原型

JavaScript OOP 概念:基於類別與基於原型

Mary-Kate Olsen
Mary-Kate Olsen原創
2024-10-20 14:34:29503瀏覽

JavaScript OOP Concepts: Class-Based vs. Prototype-Based要撰寫有關JavaScript 物件導向程式設計(OOP) 概念和原型的詳細博客,我們將首先介紹一等函數 -類別實例繼承多態性封裝抽象,解釋基於類別的基於原型的 方法。


JavaScript 的獨特之處在於它可以支援基於類別的 OOP(在 ES6 中引入)和基於原型的 OOP(JavaScript 處理 OOP 的原始方式)。本部落格將深入探討關鍵的OOP 概念,例如一等函數一等實例繼承多態性封裝抽象使用這兩種方法。

1.一流的功能

在 JavaScript 中,函數是一等公民。這表示函數可以是:

  • 分配給變數
  • 作為參數傳遞
  • 從其他函數回傳

絕對!讓我們對部落格文章進行分解,以涵蓋在 JavaScript 中使用函數式和基於類別的方法的一流函數一流實例。這將使您在物件導向程式設計 (OOP) 的背景下清楚地理解這些概念。

函數式方法

範例:一等函數

// Assigning a function to a variable
const greet = function(name) {
  return `Hello, ${name}!`;
};

// Passing a function as an argument
function logGreeting(fn, name) {
  console.log(fn(name));
}

// Returning a function
function createMultiplier(multiplier) {
  return function(number) {
    return number * multiplier;
  };
}

logGreeting(greet, "John");  // Output: Hello, John!

const double = createMultiplier(2);
console.log(double(5));  // Output: 10

說明:

  • 函數可以像任何其他值一樣儲存、傳遞和返回,展示一流的函數

基於類別的方法

雖然函數是一等公民,但我們也可以創造模仿類似行為的類別。

範例:類別上下文中的一流函數

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

  greet() {
    return `Hello, ${this.name}!`;
  }
}

// Logging greeting
class Logger {
  static logGreeting(greeter) {
    console.log(greeter.greet());
  }
}

// Using classes to demonstrate first-class functions
const greeter = new Greeter("John");
Logger.logGreeting(greeter); // Output: Hello, John!

說明:

    Greeter 類別透過封裝greet 方法演示了一流的類似函數的行為,該方法可以傳遞給其他函數(如 logGreeting)。

2.一級實例

物件或類別的實例也可以被視為

一等公民。它們可以分配給變量,作為參數傳遞,並儲存在集合中。

與函數一樣,物件或類別的實例也可以被視為

一等公民。他們可以是:

  • 分配給變數
  • 作為參數傳遞
  • 從函數回傳
  • 儲存在陣列等集合中

函數式方法

範例:第一類實例

// Assigning a function to a variable
const greet = function(name) {
  return `Hello, ${name}!`;
};

// Passing a function as an argument
function logGreeting(fn, name) {
  console.log(fn(name));
}

// Returning a function
function createMultiplier(multiplier) {
  return function(number) {
    return number * multiplier;
  };
}

logGreeting(greet, "John");  // Output: Hello, John!

const double = createMultiplier(2);
console.log(double(5));  // Output: 10

說明:

  • 這裡,myCar 和 yourCar 是 Car 函式建構子的實例。它們可以傳遞給函數並儲存在變數中。

基於類別的方法

範例:類別上下文中的第一類實例

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

  greet() {
    return `Hello, ${this.name}!`;
  }
}

// Logging greeting
class Logger {
  static logGreeting(greeter) {
    console.log(greeter.greet());
  }
}

// Using classes to demonstrate first-class functions
const greeter = new Greeter("John");
Logger.logGreeting(greeter); // Output: Hello, John!

說明:

  • 在此範例中,myCar 和 yourCar 是 Car 類別的實例,就像函數式方法一樣,它們可以傳遞給函數並進行操作。

3.繼承

基於類別的繼承允許您使用extends關鍵字建立一個從現有類別繼承屬性和方法的新類別。

基於類別的範例:

function Car(make, model) {
  this.make = make;
  this.model = model;

  this.startEngine = function() {
    console.log(`${this.make} ${this.model} engine started.`);
  };
}

const myCar = new Car("Toyota", "Corolla");
const yourCar = new Car("Tesla", "Model 3");

// Passing instance as an argument
function showCarDetails(car) {
  console.log(`Car: ${car.make} ${car.model}`);
}

showCarDetails(myCar);  // Output: Car: Toyota Corolla

基於原型的範例:

class Car {
  constructor(make, model) {
    this.make = make;
    this.model = model;
  }

  startEngine() {
    console.log(`${this.make} ${this.model} engine started.`);
  }
}

const myCar = new Car("Toyota", "Corolla");
const yourCar = new Car("Tesla", "Model 3");

// Passing instance as an argument
function showCarDetails(car) {
  console.log(`Car: ${car.make} ${car.model}`);
}

showCarDetails(myCar);  // Output: Car: Toyota Corolla

說明:

  • 基於類別的繼承使用extends從父類別繼承,而基於原型的繼承使用Object.create來連結物件。

4.多態性

多態允許不同的物件定義相同方法的自己的版本,可以在父類型的物件上呼叫。

基於類別的範例:

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

  speak() {
    console.log(`${this.name} makes a sound.`);
  }
}

class Dog extends Animal {
  speak() {
    console.log(`${this.name} barks.`);
  }
}

const myDog = new Dog("Buddy");
myDog.speak();  // Output: Buddy barks.

基於原型的範例:

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

Animal.prototype.speak = function() {
  console.log(`${this.name} makes a sound.`);
};

function Dog(name) {
  Animal.call(this, name);  // Inherit properties
}

Dog.prototype = Object.create(Animal.prototype);  // Inherit methods
Dog.prototype.constructor = Dog;

Dog.prototype.speak = function() {
  console.log(`${this.name} barks.`);
};

const myDog = new Dog("Buddy");
myDog.speak();  // Output: Buddy barks.

說明:

  • 多態性 允許基於類別和基於原型的物件定義自己的發言方法版本,同時仍從父類型繼承。

5.封裝

封裝涉及隱藏物件的內部細節並僅公開必要的內容。在 JavaScript 中,我們透過在 基於類別的 OOP 中使用私有欄位(帶有 #)或在 基於原型的 OOP 中使用閉包來實現這一點。

基於類別的範例:

class Animal {
  speak() {
    console.log("Animal makes a sound.");
  }
}

class Dog extends Animal {
  speak() {
    console.log("Dog barks.");
  }
}

class Cat extends Animal {
  speak() {
    console.log("Cat meows.");
  }
}

const animals = [new Dog(), new Cat()];

animals.forEach(animal => animal.speak());
// Output:
// Dog barks.
// Cat meows.

基於原型的範例:

function Animal() {}

Animal.prototype.speak = function() {
  console.log("Animal makes a sound.");
};

function Dog() {}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.speak = function() {
  console.log("Dog barks.");
};

function Cat() {}

Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.speak = function() {
  console.log("Cat meows.");
};

const animals = [new Dog(), new Cat()];
animals.forEach(animal => animal.speak());
// Output:
// Dog barks.
// Cat meows.

說明:

  • 基於類別的封裝使用私有欄位(ES6中引入)來隱藏數據,而基於原型的封裝透過閉包實現隱私。

6.抽象

抽象隱藏複雜的邏輯,只暴露必要的細節。它可以透過抽像出內部細節並公開基本方法來實現。

基於類別的範例:

// Assigning a function to a variable
const greet = function(name) {
  return `Hello, ${name}!`;
};

// Passing a function as an argument
function logGreeting(fn, name) {
  console.log(fn(name));
}

// Returning a function
function createMultiplier(multiplier) {
  return function(number) {
    return number * multiplier;
  };
}

logGreeting(greet, "John");  // Output: Hello, John!

const double = createMultiplier(2);
console.log(double(5));  // Output: 10

基於原型的範例:

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

  greet() {
    return `Hello, ${this.name}!`;
  }
}

// Logging greeting
class Logger {
  static logGreeting(greeter) {
    console.log(greeter.greet());
  }
}

// Using classes to demonstrate first-class functions
const greeter = new Greeter("John");
Logger.logGreeting(greeter); // Output: Hello, John!

說明:

  • 這兩種方法都封裝了管理電池電量的複雜性,僅公開了必要的互動方法。

結論

了解 JavaScript 中基於類別基於原型 OOP 之間的差異和相似之處可以增強您的程式設計技能。一流的函數和實例、繼承、多態性、封裝和抽象化是基本概念,您可以利用它們來編寫更清晰、更易於維護的程式碼。

雖然現代基於類別的 語法(在ES6 中引入)對於來自其他OOP 語言的開發人員來說更具可讀性和熟悉性,但基於原型 方法對於JavaScript 來說更為基礎潛在行為。

本部落格示範了核心OOP 概念— 第一類函數第一類實例繼承多態性封裝抽象——兩種範式都可以實現。無論您使用類別還是原型,JavaScript 都提供了強大的機制,以靈活且強大的方式實現 OOP。


以上是JavaScript OOP 概念:基於類別與基於原型的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn