」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > JS 中的 OOP -

JS 中的 OOP -

發佈於2024-11-04
瀏覽:418

OOP in JS -

  • JS 类就像语法糖,与其他强类型语言的类不同。
  • 仅添加语法包装以使来自其他语言的开发人员熟悉。
  • 类是一种特殊类型的幕后函数,因此可以写为类表达式和类声明。
## class expression:
const Person = class {
}

## class declaration:
class Person {
  constructor(fName, bYear){
   this.fName = fName;
   this.bYear = bYear;
  }
  calcAge(){
   console.log(2024 - this.bYear);
  }
}

- constructor is a method of this class. Pass values for properties to have in objects created using this fn.
- then set the properties of the object using this.xxx = xxx;
- On using 'new' operator, this constructor will be called automatically and return a new object which will be stored in LHS variable as shown below.
Ex. const ronald = new Person('ronald',1975); // Person { fName: 'ronald', bYear: 1975 }
- Methods are written outside the constructor fn and will be added to the prototype property of the object which can be verified using devConsole.
Ex. ronald.calcAge(); // 49

ronald.__proto__ === Person.prototype; // true

- No commas need to be added while adding multiple methods below the constructor fn inside the class.

## Hence, the above syntax works same as constructor fn syntax but with a familiar syntax of strongly typed class based languages.

## Adding a fn explicitly to the prototype:
Person.prototype.greet = function(){
console.log(`Hey ${this.fName}`);
}
ronald.greet(); // 'Hey ronald'

导入点:

  • Fn 声明被提升,而 Class 声明不被提升。
  • 也是一等公民,就像 Fns 一样,即可以传递给 fns 并从 fns 返回。
  • 无论我们是否激活严格模式,类的主体总是在严格模式下执行。
  • 类使代码看起来更干净,如果您知道它是如何在幕后实现的,则可以减少字符噪音。 ** 要成为 JS 专家,您需要了解复杂的语言实现细节,例如类。

访问器属性:获取器和设置器,即获取和设置值的 fns。但从外观上看,它们仍然像普通属性。

普通属性称为数据属性。

  • Getter 和 Settter 是 JS 中所有对象所共有的,即每个对象都可以有 getter 和 setter 属性。这些 getter-setter 称为访问器属性,而普通属性称为数据属性。

- Getter 和 setter 是获取和设置值的 fns,从外部看起来就像普通属性。

const account = {
  owner: 'jonas',
  movements: [200,300,100,500],
  get latest(){
    // will return an array with last value. Hence, use pop to get the value.
    return this.movements.slice(-1).pop();
  },
  set latest(mov){
    this.movements.push(mov);
  }
}

account.latest; // 500
account.latest = 50; 
account.latest; // 50

Just like above, classes also support the getter-setter methods but acccessed like using a property syntax.

These are very useful for data validation.

静态方法

前任。 Array.from() = 将类似数组的结构转换为数组。
Array.from(document.querySelector('h1'));
Array.from(document.querySelectorAll('h1'));

前任。 .from 附加到数组构造函数,而不是构造函数的原型属性。因此,并非所有数组都继承此 fn.
[1,2,3].from(); // .from 不是函数

前任。 Number.parseFloat(12) 是 Number 构造函数上的静态方法,不适用于数字变量。

创建静态方法。

// Static methods are not inherited. They are not added to prototype.
className.fnName = function(){
  console.log(this); // Entire constructor() which is calling the method
  console.log("JS is awesome")
};
className.fnName();

// Rule =  whatever object is calling the method, 'this' points to that object inside the fn. Hence its simply the entire constructor() above.

//Inside class, we need to use static keyword for adding a static method.
static fnName = function(){
  console.log(this); // can point to the entire class defn
  console.log("JS is awesome")
};

// Static methods and instance methods will be different from each other.
// instance methods will be prototype, hence all instances can have access to them

对象.create():

手动用于将对象的原型设置为我们想要的任何对象。
将用于实现继承黑白类。
使用此 fn 实现原型继承。
Object.create 返回一个空对象。
与构造函数 fns 和类的工作方式不同。
即使不涉及“prototype”、“constructor()”、“new”运算符,仍然存在原型继承的想法。

const PersonProto = {
  // This method will be looked up using __proto__ link
  calcAge(){
    console.log(2024 - this.bYear);
  }
};

// baba will be created, with its prototype set to PersonProto object.
const baba = Object.create(PersonProto);
baba;

baba.name = 'Roger';
baba.bYear = '2000';
baba.calcAge();

构造函数 Fn --(.prototype)--> Person.prototype
对象实例 --(proto)--> Person.prototype

工作方式就像在 fn 构造函数或类中一样
不需要 constructor() 或 .prototype 属性来实现此目标。

const PersonProto = {
  // This method will be looked up using __proto__ link
  calcAge(){
    console.log(2024 - this.bYear);
  },
  // Noting special with init name, its a normal fn here.
  // This has nothing to with ES6 constructor()
  // Manual way of initialzing an object.
  init(fName, bYear){
    this.fName = fName;
    this.bYear = bYear;
  }
};

// baba will be created, with its prototype set to PersonProto object.
const baba = Object.create(PersonProto);
baba;

baba.name = 'Roger';
baba.bYear = '2000';
baba.calcAge();

baba.__proto__;    // { calcAge: [Function: calcAge] }
baba.__proto__ === PersonProto; //true


const alice = Object.create(PersonProto);
alice.init("alice", 2000);
alice;   // { fName: 'alice', bYear: 2000 }  

创建原型继承的方法:
构造函数 Fn
ES6 类
对象.create

使用constructor()在类之间进行继承:

所有这些技术都允许对象在其原型上查找方法。
JS 中不存在真正的类。

const Person = function(firstName, bYear){
  this.firstName = firstName;
  this.bYear = bYear;
};

Person.prototype.calcAge = function(){
  console.log(2024 - this.bYear);
};

const Student = function(firstName, bYear, course){
  // This is the duplicate code, any change in Person won't be reflected here.
  this.firstName = firstName;
  this.bYear = bYear;
  this.course = course;
};

Student.prototype.introduce = function(){
  console.log(`My name is ${this.firstName} and I study ${this.course}`);
}

const matt = new Student("Matt", 2000, "CSE");
matt.introduce(); //  'My name is Matt and I study CSE'

删除上面示例中的冗余代码:

const Person = function(firstName, bYear){
  this.firstName = firstName;
  this.bYear = bYear;
};

Person.prototype.calcAge = function(){
  console.log(2024 - this.bYear);
};

const Student = function(firstName, bYear, course){
  // Person(firstName, bYear); -> This doesn't work because we are calling it as a regular fn call. 'new' has to be used to call this fn constructor. This fn call is simply a regular fn call, in which 'this' is set 'undefined'. Hence, an error as it cannot set firstName on undefined.
  // We want to set the 'this' inside this fn to be same as inside Person above.
  Person.call(this, firstName, bYear);
  this.course = course;
};

Student.prototype.introduce = function(){
  console.log(`My name is ${this.firstName} and I study ${this.course}`);
}

const matt = new Student("Matt", 2000, "CSE");
matt.introduce(); //  'My name is Matt and I study CSE'

'new' 通过 proto
在对象实例与其原型之间自动建立链接 继承的整个思想是子类可以共享原型链上父类的行为。
原型[Object.prototype] = null; // 位于原型链的顶部。

const Person = function(firstName, bYear){
  this.firstName = firstName;
  this.bYear = bYear;
};

Person.prototype.calcAge = function(){
  console.log(2024 - this.bYear);
};

const Student = function(firstName, bYear, course){
  Person.call(this, firstName, bYear);
  this.course = course;
};

// Student.prototype = Person.prototype; => This doesn't work because we won't get the prototype chain, rather we will get 
// Constructor fn[i.e Person()]    --------------> Person.prototype
// Constructor fn[i.e Student()]   --------------> Person.prototype
// Object [Matt] __proto__: Student.prototype ---> Person.prototype

// Student.prototype manually linked for lookup to Person.prototype.
// This has to be done here and not after else Object.create will overwrite any of the existing methods like introduce() on it.
Student.prototype = Object.create(Person.prototype);

Student.prototype.introduce = function(){
  console.log(`My name is ${this.firstName} and I study ${this.course}`);
}

const matt = new Student("Matt", 2000, "CSE");
matt.introduce(); //  'My name is Matt and I study CSE'
matt.calcAge();    // 24

matt.__proto__;                   // Person { introduce: [Function (anonymous)] }
matt.__proto__.__proto__;        // { calcAge: [Function (anonymous)] }
matt.__proto__.__proto__.__proto__;   // [Object: null prototype] {}

Student.prototype.constructor = Student;   // [Function: Student]

matt instanceof Student; // true
matt instanceof Person; // true
matt instanceof Object; // true
版本聲明 本文轉載於:https://dev.to/mahf001/oops-in-js-22-5a2n?1如有侵犯,請洽[email protected]刪除
最新教學 更多>
  • Ubuntu 升級後如何解決 Python 中的「ImportError: No module named 'encodings'」?
    Ubuntu 升級後如何解決 Python 中的「ImportError: No module named 'encodings'」?
    解決Ubuntu升級後Python中的「ImportError: No module name 'encodings'」問題無法取得語言環境編碼時出現的問題,導致錯誤訊息「ImportError:沒有名為'encodings'的模組。」儘管重新安裝Python 並設定...
    程式設計 發佈於2024-11-17
  • 簡單工廠
    簡單工廠
    什么是简单工厂? 简单工厂不是设计模式。它只是将对象创建与客户端代码解耦。换句话说,简单工厂通过将实例化逻辑移至单独的类来封装对象实例化。 简单工厂经常与工厂模式混淆。我们将研究简单工厂来阐明它们的区别。另外,学习简单工厂可以帮助我们轻松理解工厂模式。 简单工厂可以...
    程式設計 發佈於2024-11-17
  • 在 Go 中使用 WebSocket 進行即時通信
    在 Go 中使用 WebSocket 進行即時通信
    构建需要实时更新的应用程序(例如聊天应用程序、实时通知或协作工具)需要一种比传统 HTTP 更快、更具交互性的通信方法。这就是 WebSockets 发挥作用的地方!今天,我们将探讨如何在 Go 中使用 WebSocket,以便您可以向应用程序添加实时功能。 在这篇文章中,我们将介绍: WebSoc...
    程式設計 發佈於2024-11-17
  • 為什麼我的 Laravel 網站在將 Apache 升級到 2.4 並將 PHP 升級到 5.5.7 後顯示空白畫面?
    為什麼我的 Laravel 網站在將 Apache 升級到 2.4 並將 PHP 升級到 5.5.7 後顯示空白畫面?
    Laravel 網站在Apache 升級後顯示空白畫面Laravel 網站在Apache 升級後顯示空白畫面在升級到Apache 2.4 和PHP 5.5.7 之前,我的Laravel 網站運作正常。但是,我現在在訪問 laravel.mydomain.example 時遇到空白畫面。 Apache...
    程式設計 發佈於2024-11-17
  • Bootstrap 4 Beta 中的列偏移發生了什麼事?
    Bootstrap 4 Beta 中的列偏移發生了什麼事?
    Bootstrap 4 Beta:列偏移的刪除和恢復Bootstrap 4 在其Beta 1 版本中引入了重大更改柱子偏移了。然而,隨著 Beta 2 的後續發布,這些變化已經逆轉。 從 offset-md-* 到 ml-auto在 Bootstrap 4 Beta 1 中, offset-md-*...
    程式設計 發佈於2024-11-17
  • 大批
    大批
    方法是可以在物件上呼叫的 fns 數組是對象,因此它們在 JS 中也有方法。 slice(begin):將陣列的一部分提取到新數組中,而不改變原始數組。 let arr = ['a','b','c','d','e']; // Usecase: Extract till index ...
    程式設計 發佈於2024-11-17
  • 如何在 PHP 中組合兩個關聯數組,同時保留唯一 ID 並處理重複名稱?
    如何在 PHP 中組合兩個關聯數組,同時保留唯一 ID 並處理重複名稱?
    在 PHP 中組合關聯數組在 PHP 中,將兩個關聯數組組合成一個數組是常見任務。考慮以下請求:問題描述:提供的代碼定義了兩個關聯數組,$array1和$array2。目標是建立一個新陣列 $array3,它合併兩個陣列中的所有鍵值對。 此外,提供的陣列具有唯一的 ID,而名稱可能重疊。要求是建構一...
    程式設計 發佈於2024-11-17
  • Numpy 備忘單
    Numpy 備忘單
    Comprehensive Guide to NumPy: The Ultimate Cheat Sheet NumPy (Numerical Python) is a fundamental library for scientific computing in Python. ...
    程式設計 發佈於2024-11-17
  • 你需要像專業人士一樣閱讀科技文章
    你需要像專業人士一樣閱讀科技文章
    在快节奏的技术世界中,并非您阅读的所有内容都是准确或公正的。并非您读到的所有内容都是由人类编写的! 细节可能存在微妙的错误,或者文章可能故意误导。让我们来看看一些可以帮助您阅读科技文章或任何媒体内容的技能。 1. 培养健康的怀疑态度 培养健康的怀疑态度至关重要。质疑大胆的主张,寻找...
    程式設計 發佈於2024-11-17
  • 如何找到一個多維數組中存在但另一個多維數組中不存在的行?
    如何找到一個多維數組中存在但另一個多維數組中不存在的行?
    比較多維數組的關聯行您有兩個多維數組,$pageids 和$parentpage,其中每行代表一個包含列的記錄“id”、“連結標籤”和“url”。您想要尋找 $pageids 中存在但不在 $parentpage 中的行,從而有效地建立一個包含缺少行的陣列 ($pageWithNoChildren)...
    程式設計 發佈於2024-11-17
  • 為什麼 Windows 中會出現「Java 無法辨識」錯誤以及如何修復它?
    為什麼 Windows 中會出現「Java 無法辨識」錯誤以及如何修復它?
    解決Windows 中的「Java 無法識別」錯誤嘗試在Windows 7 上檢查Java 版本時,使用者可能會遇到錯誤「'Java' 無法識別”作為內部或外部命令。 」此問題通常是由於缺少Java 安裝或環境變數不正確而引起的。要解決此問題,您需要驗證Java 安裝並配置必要的環境...
    程式設計 發佈於2024-11-17
  • 儘管檔案存在且有權限,為什麼 File.delete() 會回傳 False?
    儘管檔案存在且有權限,為什麼 File.delete() 會回傳 False?
    儘管存在並進行權限檢查,File.delete() 返回False使用FileOutputStream 寫入檔案後嘗試刪除檔案時,某些使用者遇到意外問題: file.delete() 傳回false。儘管檔案存在且所有權限檢查(.exists()、.canRead()、.canWrite()、.ca...
    程式設計 發佈於2024-11-17
  • 如何有效地從 Go 中的切片中刪除重複的對等點?
    如何有效地從 Go 中的切片中刪除重複的對等點?
    從切片中刪除重複項給定一個文字文件,其中包含表示為具有“Address”和“PeerID”的對象的對等點清單屬性,任務是根據程式碼配置中「Bootstrap」切片中匹配的「Address」和「PeerID」刪除所有重複的對等點。 為了實現此目的,我們迭代切片中的每個對等點物件多次。在每次迭代期間,我...
    程式設計 發佈於2024-11-17
  • 如何自訂Bootstrap 4的檔案輸入元件?
    如何自訂Bootstrap 4的檔案輸入元件?
    繞過 Bootstrap 4 檔案輸入的限制Bootstrap 4 提供了自訂檔案輸入元件來簡化使用者的檔案選擇。但是,如果您希望自訂「選擇檔案...」佔位符文字或顯示所選檔案的名稱,您可能會遇到一些挑戰。 更改 Bootstrap 4.1 及更高版本中的佔位符自 Bootstrap 4.1 起,佔...
    程式設計 發佈於2024-11-17
  • 如何在 CSS 盒子上創建斜角?
    如何在 CSS 盒子上創建斜角?
    在 CSS 框上建立斜角可以使用多種方法在 CSS 框上實現斜角。一種方法描述如下:使用邊框的方法此技術依賴於沿容器左側建立透明邊框和沿底部建立傾斜邊框。以下程式碼示範如何實現:<div class="cornered"></div> <div cl...
    程式設計 發佈於2024-11-17

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3