首頁  >  文章  >  web前端  >  JS 中的物件導向編程

JS 中的物件導向編程

PHPz
PHPz原創
2024-08-29 13:39:211108瀏覽

OOP in JS

範式是指程式碼的風格及其組織方式。常見的程式設計範式有:OOP、函數式等。要成為開發人員,您需要很好地了解 OOP。

物件導向程式設計

  • 最受歡迎的企業程式設計範例。
  • 基於物件
  • 以組織程式碼為目標而開發
  • 讓程式碼更加靈活、可維護。
  • 在 OOP 之前,程式碼分散在全域範圍內的多個 fns 中,沒有任何結構。這種風格被稱為義大利麵程式碼,很難​​維護,忘記添加新功能。
  • 用於透過程式碼建立物件。
  • 還可以實現物件之間的互動。

API

  • 物件外部的程式碼可以存取並用於與其他物件通訊的方法。

班級

  • 用於建立物件的抽象藍圖。
  • 從類別實例化,即使用類別藍圖建立。
  • 使用「new Class()」語法從一個類別建立多個物件

課程設計:

  • 使用 OOP 的 4 個原則完成,即抽象、封裝、繼承、多態
  • 抽象:隱藏對最終使用者來說無關緊要的不必要的細節。
  • 封裝:將一些屬性方法保持為私有,這使得它們只能從類別內部訪問,並且無法從類別外部存取。公開一些方法作為與外部世界互動的公共介面 API。因此,它可以防止外部程式碼操縱內部狀態[物件的資料],因為這可能是錯誤的重要來源。公共介面是非私有的程式碼。將方法設為私有使我們可以更輕鬆地更改程式碼的實現,而不會破壞外部依賴關係。總結:很好地封裝狀態和方法,隻公開必要的方法。
  • 繼承:重複的程式碼很難維護。因此,這個概念透過繼承已經編寫的程式碼來支援程式碼的可重用性。子類別透過繼承父類別的所有屬性和方法來擴展父類別。此外,子類別實作了自己的資料功能以及繼承的功能。
  • 多態性:子類別可以覆寫從父類別繼承的方法。

物件是:

  • 用於對現實世界或抽象特徵進行建模。
  • 可能包含資料(屬性)和程式碼(方法)。幫助我們將資料和程式碼打包在一個區塊中
  • 獨立的程式碼片段/區塊。
  • appln的構建塊,相互互動。
  • 黑白物件的互動透過公共介面API發生。
  • 從類別建立的所有物件稱為該類別的實例。
  • 所有物件都可以包含不同的數據,但它們都共享共同的功能

經典傳承:

  • 支援Java、C++、Python等
  • 一個類別繼承另一個類別
  • 方法或行為從類別複製到所有實例。

JS 中的委託或原型繼承:

  • 像古典語言一樣支持所有 OOP 原則。
  • 從類別繼承的實例。
  • 原型包含所有連結到該原型的物件都可以存取的方法。 原型:包含方法 object:可以存取原型的方法,使用proto連結連接到原型物件。
  • 物件繼承原型物件上定義的屬性和方法。
  • 物件將行為委託給原型物件。
  • 使用者定義的陣列實例透過 proto 連結存取 Array.prototype.map() 上的 .map(),也就是原型物件上定義的 map()。因此,.map() 不是在我們的實例上定義的,而是在原型上定義的。
## 3 Ways to implement Prototypal Inheritance via:
1. Constructor Fn:
- To create objects via function.
- Only difference from normal fn is that they are called with 'new' operator.
- Convention: always start with a capital letter to denote constructor fn. Even builtins like Array, Map also follow this convention.
- An arrow function doesn't work as Fn constructor as an arrow fn doesn
t have its own 'this' keyword which we need with constructor functions.
- Produces an object. 
- Ex. this is how built-in objects like Array, Maps, Sets are implemented

2. ES6 Classes:
- Modern way, as compared to above method.
- Syntactic sugar, although under the hood work the same as above syntax.
- ES6 classes doesn't work like classical OOP classes.

3. Object.create()
- Way to link an object to its prototype
- Used rarely due to additional repetitive work.

## What does 'new' operator automates behind the scene?
1. Create an empty object {} and set 'this' to point to this object.
2. Create a __proto__ property linking the object to its parent's prototype object.
3. Implicit return is added, i.e automatically return 'this {} object' from the constructor fn.

- JS doesn't have classes like classical OOP, but it does create objects from constructor fn. Constructor fn have been used since inception to simulate class like behavior in JS.
Ex. validate if an object is instance of a constructor fn using "instanceOf" operator.

const Person = function(fName, bYear) {
  // Instance properties as they will be available on all instances created using this constructor fn.
  this.fName = fName;
  this.bYear = bYear;

  // BAD PRACTICE: NEVER CREATE A METHOD INSIDE A CONSTRUCTOR FN.
  this.calcAge = function(){
console.log(2024 - this.bYear);
}
};

const mike = new Person('Mike', 1950);
const mona = new Person('Mona', 1960);
const baba = "dog";

mike; // Person { fName: 'Mike', bYear: 1950 }
mona; // Person { fName: 'Mona', bYear: 1960 }

mike instanceof Person; // true
baba instanceof Person; // true


If there are 1000+ objects, each will carry its own copy of fn defn.
Its a bad practice to create a fn inside a contructor fn as it would impact performance of our code.

原型物件:

  • 每個函數,包括JS中的建構子fn,都有一個名為prototype物件的屬性。
  • 從此建構子 fn 建立的每個物件都可以存取建構子 fn 的原型物件。前任。 Person.prototype
  • 透過以下方式將 fn 加入此原型物件: Person.prototype.calcAge = function(bYear){ console.log(2024 年 - bYear); };

mike.calcAge(1970); // 54
莫娜.calcAge(1940); // 84

  • mike 物件不會包含 .calcAge(),但它將使用 Person.prototype 物件上定義的 proto 連結來存取它。
  • 'this' 總是設定為呼叫函數的物件。

麥克。 原型; // { calcAge: [函數(匿名)] }
莫娜。 原型; // { calcAge: [函數(匿名)] }

麥克。 原型 === Person.prototype; // true

  • Person.prototype here serves as prototype for all the objects, not just this single object created using Person constructor fn.

Person.prototype.isPrototypeOf(mike); // true
Person.prototype.isPrototypeOf(Person); // false

  • prototype should have been better named as prototypeOfLinkedObjects generated using the Constructor fn.
  • Not just methods, we can create properties also on prototype object. Ex. Person.prototype.creatureType = "Human"; mike.creatureType; // Human mona.creatureType; // Human

Different properties for an object:

  • Own property and properties on constructor fn accessbile via proto link of objects.
  • To check own property for objects, use:
    mike.hasOwnProperty('fName'); // true
    mona.hasOwnProperty('creatureType'); // false

  • Two way linkage:
    Person() - constructor fn
    Person.prototype - Prototype

Person() constructor fn links to Person.prototype via .prototype
Person.prototype prototype links back to Person() constructor fn via .constructor to Person() itself.

proto : always points to Object's prototype for all objects in JS.
newly created object is automatically returned, unless we explicitly return something else and stored in the LHS variable declared.

Prototype Chain:

  • Similar to scope chain. Look for variable in the scope level
  • Prototype chain has to lookup for finding properties or methods.
  • All objects in JS has a proto link Person Person.proto Person.proto.proto; // [Object: null prototype] {}

Top Level Object in JS:
Object() - constructor fn
Object.prototype - Prototype
Object.prototype.proto // null

Object.prototype methods:

  • constructor: f Object()
  • hasOwnProperty
  • isPrototypeOf
  • propertyIsEnumerable
  • toLocaleString
  • toString
  • valueOf
  • defineGetter etc

// Takes to constructor fn prototype
mike.proto === Person.prototype; // true
// Takes to parent of constructor fn's prototype i.e Object fn
mike.proto.proto; // [Object: null prototype] {}
// Takes to parent of Object fn i.e end of prototype chain
mike.proto.proto.proto; // null

  • All fns in JS are objects, hence they also have a prototype
  • console.dir(x => x+1);
  • Fns are objects, and objects have prototypes. So a fn prototype has methods which can be called.
  • const arr = [2,4,21]; // is same as using 'new Array' syntax
    arr.proto; // shows fns on array's prototype

  • Each array doesn't have all of these methods, its able to use it via proto link.

  • arr.proto === Array.prototype; // true

const arr = [2,4,21];
arr.proto; // Array prototype
arr.proto.proto; // Object prototype
arr.proto.proto.proto; // null

## If we add a fn to Array.prototype, then all newly created arrays will inherit that method. However extending the prototype of a built-in object is not a good idea. Incase new version of JS adds a method with the same name, will break your code. Or in case multiple Devs create similar fnality with different names will add an unnecessary overhead.
Ex. Add a method named unique to get unique values
const arr = [4,2,4,1,2,7,4,7,3];
Array.prototype.uniq = function(){
return [...new Set(this)];
}
arr.uniq(); // [ 4, 2, 1, 7, 3 ]
  • All DOM elements behind the scene are objects.
  • console.dir(h1) // will show you it in object form
  • Prototype chain: h1 -> HTMLHeadingElement -> HTMLElement -> Element -> Node -> EventTarget -> Object

以上是JS 中的物件導向編程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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