跳到主要內容

過去的 JS 互通性

本頁說明 Dart 的 JS 互通性的先前迭代,這些迭代已被視為舊版,並在 Dart 3.7 中被棄用。因此,建議今後優先使用 dart:js_interop,並在可能的情況下遷移舊互通性程式庫的用法。雖然 dart:html 和其他 Web 程式庫密切相關,但它們在 package:web 頁面中介紹。

dart:js

#

dart:js 公開了一個具體的 物件包裝器,用於與 JS 物件互通。此包裝器包含基於字串的方法,用於動態取得、設定和呼叫包裝的 JS 物件上的屬性。由於包裝成本,它的效能較差,而且在人體工學上更難以使用。例如,您沒有程式碼完成功能,因為您無法宣告互通性成員,而是依賴字串。dart:js 中公開的許多功能(例如 allowInterop)後來透過其他互通性程式庫重新公開。

自從 package:jsdart:js_util 發布以來,此程式庫已成為舊版。

package:js

#

package:js 引入了宣告互通性類型和成員的功能。它允許使用者編寫互通性類別,而不是互通性擴展類型。在執行時期,這些類別會被抹除為類似於 dart:js_interopJSObject 的類型。

dart
@JS()
class JSType {}

package:js 的使用者會發現 dart:js_interop 的語法和語意很熟悉。您可以透過將類別定義替換為擴展類型來遷移到 dart:js_interop,並且在許多情況下都可以運作。

但是,存在顯著差異

  • package:js 類型不能用於與瀏覽器 API 互通。dart:js_interop 類型可以。
  • package:js 允許動態調度。這表示如果您將 package:js 類型轉換為 dynamic 並在其上呼叫互通性成員,它會轉發到正確的成員。使用 dart:js_interop 時,這不再可能。
  • package:js@JS 沒有健全性保證,因為未檢查 external 成員的回傳類型。dart:js_interop 是健全的。
  • package:js 類型無法重新命名實例成員或擁有非 external 成員。
  • package:js 類型可以子類型化,並且可以是非互通性類別的超類型。這通常用於模擬。使用 dart:js_interop 時,模擬是透過替換 JS 物件來完成的。請參閱關於模擬的教學課程
  • @anonymous 類型是一種使用物件字面建構子宣告互通性類型的方式。dart:js_interop 不會以這種方式區分類型,而且任何 external 具名引數建構子都是物件字面建構子。

@staticInterop

#

除了 @JS@anonymous 之外,package:js 後來公開了 @staticInterop,這是互通性擴展類型的原型。它與 dart:js_interop 一樣具有表達性和限制性,並且旨在成為擴展類型可用之前的過渡語法。

@staticInterop 類型會隱含地抹除為 JSObject。它要求使用者在擴展中宣告所有實例成員,以便只能使用靜態語意,並具有更強的健全性保證。使用者可以使用它與瀏覽器 API 互動,並且它也允許重新命名和非 external 成員等功能。與互通性擴展類型一樣,它不支援動態調度。

@staticInterop 類別幾乎總是可以遷移到互通性擴展類型,只需將類別變更為擴展類型並移除註解即可。

dart:js_interop 公開了 @staticInterop(和 @anonymous,但僅當也使用 @staticInterop 時)以支援靜態互通性語意,直到將擴展類型新增到語言中。所有此類類型現在都應遷移到擴展類型。

dart:js_util

#

dart:js_util 提供了許多實用函式,這些函式無法在 package:js 類型中宣告,或對於來回傳遞值是必要的。這包括以下成員,例如

  • allowInterop(現在是 Function.toJS
  • getProperty/setProperty/callMethod/callConstructor(現在位於 dart:js_interop_unsafe 中)
  • 各種 JS 運算子
  • 類型檢查輔助程式
  • 模擬支援
  • 以及更多。

dart:js_interopdart:js_interop_unsafe 現在包含這些輔助程式,語法可能不同。