JavaScript >> Javascript 文檔 >  >> Tags >> class

JavaScript 需要類嗎?

不管你喜不喜歡,ECMAScript 6 將會有類1 . JavaScript 中類的概念一直是兩極分化的。有些人特別喜歡 JavaScript 的無類特性,因為它與其他語言不同。另一方面,有些人討厭 JavaScript 的無類特性,因為它與其他語言不同。在從 C++ 或 Java 遷移到 JavaScript 時,人們需要跳過的最大心理障礙之一是缺少類,我曾有人向我解釋說,這是他們不喜歡 JavaScript 或決定不喜歡 JavaScript 的原因之一繼續學習。

JavaScript 自首次創建以來就沒有正式的類定義,這從一開始就引起了混亂。不乏 JavaScript 書籍和文章談論類,就好像它們是 JavaScript 中的真實事物一樣。他們所說的類實際上只是用於定義自定義引用類型的自定義構造函數。引用類型是 JavaScript 中最接近類的東西。大多數開發人員都非常熟悉通用格式,但這裡有一個示例:

function MyCustomType(value) {
    this.property = value;
}

MyCustomType.prototype.method = function() {
    return this.property;
};

在許多地方,這段代碼被描述為聲明了一個名為 MyCustomType 的類 .事實上,它所做的只是聲明一個名為 MyCustomType 的函數 旨在與 new 一起使用 創建引用類型 MyCustomType 的實例 .但是這個函數並沒有什麼特別之處,沒有什麼可以說它與任何其他不用於創建新對象的函數有什麼不同。正是函數的用法使它成為構造函數。

該代碼甚至看起來不像是在定義一個類。實際上,構造函數定義和原型上的 one 方法之間幾乎沒有明顯的關係。對於新的 JavaScript 開發人員來說,這些看起來像是兩段完全獨立的代碼。是的,這兩段代碼之間有明顯的關係,但它看起來不像用另一種語言定義一個類。

當人們開始談論繼承時,更令人困惑的是。他們立即開始拋出諸如子類和超類之類的術語,這些概念只有在您實際使用類時才有意義。當然,繼承的語法同樣令人困惑和冗長:

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

Animal.prototype.sayName = function() {
    console.log(this.name);
};

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

Dog.prototype = new Animal(null);
Dog.prototype.bark = function() {
    console.log("Woof!");
};

使用構造函數和覆蓋原型的兩步繼承過程非常令人困惑。

面向 Web 開發人員的專業 JavaScript 的第一版中 ,我專門使用了“類”這個詞。我收到的反饋表明人們對此感到困惑,因此我將第二版中對“類”的所有引用更改為“類型”。從那以後我就一直使用這個術語,它有助於消除很多混淆。

但是,仍然存在一個明顯的問題。定義自定義類型的語法令人困惑且冗長。兩種類型之間的繼承是一個多步驟的過程。沒有簡單的方法來調用超類型上的方法。底線:創建和管理自定義類型很痛苦。如果你不認為這是個問題,只需看看有多少 JavaScript 庫引入了自己的定義自定義類型、繼承或兩者的方式:

  • YUI – 有 Y.extend() 執行繼承。還添加了一個 superclass 使用此方法時的屬性。2
  • 原型 – 有 Class.create()Object.extend() 用於處理對象和“類”。3
  • 道場 – 有 dojo.declare()dojo.extend() .4
  • MooTools – 有一個名為 Class 的自定義類型 用於定義和擴展類。5

很明顯,當這麼多 JavaScript 庫都在定義解決方案時,就會出現問題。定義自定義類型很麻煩,而且一點也不直觀。 JavaScript 開發人員需要比當前語法更好的東西。

ECMAScript 6 類實際上只不過是您已經熟悉的模式之上的語法糖。考慮這個例子:

class MyCustomType {
    constructor(value) {
        this.property = value;
    }

    method() {
        return this.property;
    }
}

這個 ECMAScript 6 類定義實際上與這篇文章中的前一個示例相去甚遠。使用此類定義創建的對象與使用之前的構造函數定義創建的對象完全相同。唯一的區別是更緊湊的語法。繼承如何:

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

    sayName() {
        console.log(this.name);
    }
}

class Dog extends Animal {
    constructor(name) {
        super(name);
    }

    bark() {
        console.log("Woof!");
    }
}

此示例對前面的繼承示例進行了簡化。類定義緊湊,笨拙的多步繼承模式已被簡單的 extends 取代 關鍵詞。您還可以獲得 super() 的好處 在類定義內部,因此您無需在多個位置引用超類型。

當前所有的 ECMAScript 6 類提案都是在您已經知道的 JavaScript 模式之上的新語法。繼承的工作方式與往常一樣(原型鏈接加上調用超類型構造函數),將方法添加到原型中,並在構造函數中聲明屬性。唯一真正的區別是為您減少打字(沒有雙關語)。類定義只是語法不同的類型定義。

因此,雖然有些人因為 ECMAScript 6 引入了類而感到合適,但請記住,這個類的概念是抽象的。它並沒有從根本上改變 JavaScript 的工作方式;它不是引入新事物。類只是您已經使用了一段時間的自定義類型之上的語法糖。這解決了 JavaScript 長期以來存在的一個問題,即定義自己的類型時的冗長和混亂。我個人本來希望使用關鍵字 type 而不是 class ,但歸根結底,這只是語義問題。

那麼 JavaScript 需要類嗎?不,但是 JavaScript 肯定需要一種更簡潔的方式來定義自定義類型。恰巧這種方式在 ECMAScript 6 中有一個“類”的名稱。如果這有助於其他語言的開發人員更輕鬆地過渡到 JavaScript,那麼這是一件好事。

翻譯

  • Jeweell 團隊的烏克蘭語翻譯

參考

  1. 最大最小類↩

  2. YUI 擴展()↩

  3. 原型類和繼承↩

  4. 創建和增強 Dojo 類↩

  5. MooTools 類↩


Tutorial JavaScript 教程
  1. 將 Tailwind CSS 添加到 Angular 項目

  2. js 商店:imus

  3. 當您需要現有 SPA Web 應用程序的桌面版本時,您會怎麼做? 💡

  4. 我的 React 應用程序中檢測到無法訪問的代碼錯誤 - 如何修復?

  5. Nginx 錯誤:“您要查找的頁面暫時不可用”。我無法在我的服務器中部署 NodeJS。怎麼修?

  6. 讓 Mongooses findOneAndUpdate() 返回更新後的文檔

  7. 使用 .reduce() 將數組轉換為對象

  1. vue時鐘,動態時間顯示

  2. 如何使用 for/loop (forEach) 將多個文件上傳到 GoogleDrive API

  3. Javascript 原生條碼檢測器 API

  4. 我剛剛發布了我的新項目

  5. 簡短的東西:讓我粘貼密碼!

  6. 兩個總和 - JS(第 7 天)

  7. 在加入和離開時向我的私人頻道發送消息

  1. 使用 Auth0 對 Firebase 和 Angular 進行身份驗證:第 2 部分

  2. 如何調試服務器端渲染

  3. 使用 AWS APIGateway 和 MockIntegration 模擬 RESTful API

  4. NextJS getServerSideProps() 你好?