Scala 3 — 書籍

Scala 給 JavaScript 開發人員

語言

此頁面提供 JavaScript 和 Scala 程式語言的比較。它適用於了解 JavaScript 並想學習 Scala 的程式設計師,特別是透過查看 JavaScript 語言功能與 Scala 的比較範例。

概觀

本節提供後續各節的簡要介紹和摘要。它在高層級介紹 JavaScript 和 Scala 之間的相似性和差異,然後介紹您在撰寫程式碼時每天會遇到的差異。

高層級相似性

在高層級上,Scala 與 JavaScript 有下列相似性

  • 兩者都被視為高層級程式語言,您不必擔心指標和手動記憶體管理等低層級概念
  • 兩者都有相對簡單、簡潔的語法
  • 兩者都支援 C/C++/Java 風格的大括號語法,用於撰寫方法和其他程式碼區塊
  • 兩者都包含物件導向程式設計 (OOP) 的功能(例如類別)
  • 兩者都包含 函式式程式設計 (FP) 的功能(例如 lambda)
  • JavaScript 在瀏覽器和其他環境(例如 Node.js)中執行。因此,Scala.js 風格的 Scala 目標為 JavaScript,而 Scala 程式可以執行於相同的環境中。
  • 開發人員使用 Node.js 以 JavaScript 和 Scala 編寫伺服器端應用程式;Play Framework 等專案也讓您能以 Scala 編寫伺服器端應用程式
  • 兩種語言都有類似的 if 陳述式、while 迴圈和 for 迴圈
  • 此 Scala.js 頁面 開始,您會找到數十個支援 React、Angular、jQuery 和許多其他 JavaScript 和 Scala 函式庫
  • JavaScript 物件是可變的;Scala 物件在以命令式風格撰寫時可以是可變的
  • JavaScript 和 Scala 都支援承諾,作為處理非同步運算結果的方法(Scala 並行處理使用 future 和承諾)

高階差異

此外,在高階層面,JavaScript 和 Scala 之間的一些差異如下

  • JavaScript 是動態型別,而 Scala 是靜態型別
    • 儘管 Scala 是靜態型別,但型別推論等功能讓它感覺像動態語言(正如您將在以下範例中看到的)
  • Scala 慣用語預設偏好不可變性:建議您使用不可變變數和不可變集合
  • Scala 具有簡潔但可讀的語法;我們稱之為表達性
  • Scala 是純 OOP 語言,因此每個物件都是類別的實例,而像 ++= 這些看起來像運算子的符號實際上是方法;這表示您可以建立自己的方法,作為運算子運作
  • 作為純 OOP 語言和純 FP 語言,Scala 鼓勵 OOP 和 FP 的融合,使用函式進行邏輯處理,並使用不可變物件進行模組化
  • Scala 擁有最先進的第三方開源函式程式庫
  • Scala 中的一切都是表達式if 陳述式、for 迴圈、match 表達式,甚至 try/catch 表達式等建構式,都具有傳回值
  • Scala Native 專案讓您可以撰寫「系統」層級程式碼,並編譯為原生可執行檔

程式設計層級差異

在較低層級,以下是你撰寫程式碼時每天會看到的差異

  • Scala 變數和參數使用 val(不可變,就像 JavaScript const)或 var(可變,就像 JavaScript varlet)定義
  • Scala 不使用分號作為行尾
  • Scala 是靜態型別,儘管在許多情況下你不需要宣告型別
  • Scala 使用特質作為介面並建立混入
  • 除了簡單的 for 迴圈,Scala 還有強大的 for 理解,根據你的演算法產生結果
  • 模式配對和 match 表達式會改變你撰寫程式碼的方式
  • Scala 的 情境抽象型別推論提供一系列功能
    • 擴充方法 讓你為封閉類別新增新功能,而不會破壞模組化,因為它們只在特定範圍內可用(與猴子修補不同,猴子修補可能會污染程式碼的其他區域)
    • 給定實例 讓你定義編譯器可以用來為你合成程式碼的型別
    • 型別安全和 多重相等性 讓你限制相等性比較(在編譯時)到有意義的比較
  • 由於按名稱參數、中綴表示法、可選括號、擴充方法和 高階函式 等功能,你可以建立自己的「控制結構」和 DSL
  • 本書中你可以閱讀到的許多其他好處:案例類別、伴隨類別和物件、巨集、聯集交集 型別、多個參數清單、命名參數等等

變數和類型

註解

//
/* ... */
/** ... */
//
/* ... */
/** ... */

可變變數

let   // 現在優先用於可變變數
var   // 舊的可變樣式
var  // 用於可變變數

不可變值

const
val

Scala 的經驗法則是用 val 宣告變數,除非有特定原因需要可變變數。

命名標準

JavaScript 和 Scala 通常使用相同的 CamelCase 命名標準。變數命名為 myVariableName,方法命名為 lastIndexOf,類別和物件命名為 AnimalPrintedBook

字串

字串的許多用法在 JavaScript 和 Scala 中很相似,儘管 Scala 僅對單行字串使用雙引號,對多行字串使用三引號。

字串基礎

// 使用單引號或雙引號
let msg = 'Hello, world';
let msg = "Hello, world";
// 僅使用雙引號
val msg = "Hello, world"

內插

let name = 'Joe';

// JavaScript 使用反引號
let msg = `Hello, ${name}`;
val name = "Joe"
val age = 42
val weight = 180.5

// 在字串前使用 `s` 進行簡單內插
println(s"Hi, $name")   // "Hi, Joe"
println(s"${1 + 1}")    // "2"

// 字串前的 `f` 允許 printf 風格的格式化。
// 這個範例會印出
// "Joe is 42 years old, and weighs"
// "180.5 pounds."
println(f"$name is $age years old, and weighs $weight%.1f pounds.")

帶有內插的多行字串

let name = "joe";
let str = `
Hello, ${name}.
這是多行字串。
`;
val name = "Martin Odersky"

val quote = s"""
|$name 說
|Scala 是
|OOP 和 FP 的融合。
""".stripMargin.replaceAll("\n", " ").trim

// 結果
// "Martin Odersky 說 Scala 是 OOP 和 FP 的融合。"

JavaScript 和 Scala 也有類似的字串處理方法,包括 charAtconcatindexOf,以及更多方法。跳脫字元,例如 \n\f\t,在這兩種語言中也是相同的。

數字和算術

JavaScript 和 Scala 的數字運算子類似。最大的差異是 Scala 沒有提供 ++-- 運算子。

數字運算子

let x = 1;
let y = 2.0;
 
let a = 1 + 1;
let b = 2 - 1;
let c = 2 * 2;
let d = 4 / 2;
let e = 5 % 2;
val x = 1
val y = 2.0
 
val a = 1 + 1
val b = 2 - 1
val c = 2 * 2
val d = 4 / 2
val e = 5 % 2

遞增和遞減

i++;
i += 1;

i--;
i -= 1;
i += 1;
i -= 1;

最大的差異可能是,像 +- 這樣的「運算子」在 Scala 中實際上是方法,而不是運算子。Scala 數字也有這些相關方法

var a = 2
a *= 2      // 4
a /= 2      // 2

Scala 的 Double 類型最接近 JavaScript 的預設 number 類型,Int 表示有符號的 32 位元整數值,而 BigInt 則對應於 JavaScript 的 bigint

這些是 Scala IntDouble 值。請注意,類型不必明確宣告

val i = 1     // Int
val d = 1.1   // Double

您也可以視需要使用其他數值類型

val a: Byte = 0    // Byte = 0
val a: Double = 0  // Double = 0.0
val a: Float = 0   // Float = 0.0
val a: Int = 0     // Int = 0
val a: Long = 0    // Long = 0
val a: Short = 0   // Short = 0

val x = BigInt(1_234_456_789)
val y = BigDecimal(1_234_456.890)

布林值

兩種語言都使用 truefalse 作為布林值

let a = true;
let b = false;
val a = true
val b = false

日期

日期是兩種語言中另一種常用的類型。

取得目前日期

let d = new Date();

// 結果
// Sun Nov 29 2020 18:47:57 GMT-0700 (Mountain Standard Time)
// 取得目前日期和時間的不同方法
import java.time.*

val a = LocalDate.now
    // 2020-11-29
val b = LocalTime.now
    // 18:46:38.563737
val c = LocalDateTime.now
    // 2020-11-29T18:46:38.563750
val d = Instant.now
    // 2020-11-30T01:46:38.563759Z

指定不同的日期

let d = Date(2020, 1, 21, 1, 0, 0, 0);
let d = Date(2020, 1, 21, 1, 0, 0);
let d = Date(2020, 1, 21, 1, 0);
let d = Date(2020, 1, 21, 1);
let d = Date(2020, 1, 21);
val d = LocalDate.of(2020, 1, 21)
val d = LocalDate.of(2020, Month.JANUARY, 21)
val d = LocalDate.of(2020, 1, 1).plusDays(20)

在這種情況下,Scala 使用 Java 附帶的日期和時間類別。許多日期/時間方法在 JavaScript 和 Scala 之間類似。請參閱 java.time 套件 以取得更多詳細資訊。

函數

在 JavaScript 和 Scala 中,函數都是物件,因此它們的功能類似,但其語法和術語略有不同。

命名函數,一行

function add(a, b) {
  return a + b;
}
add(2, 2);   // 4
// 技術上來說這是一個方法,而不是函數
def add(a: Int, b: Int) = a + b
add(2, 2)   // 4

命名函數,多行

function addAndDouble(a, b) {
  // 假設這需要
  // 多行
  return (a + b) * 2
}
def addAndDouble(a: Int, b: Int): Int =
  // 假設這需要
  // 多行
  (a + b) * 2

在 Scala 中,顯示 Int 回傳類型是可選的。它在 add 範例中沒有顯示,而在 addAndDouble 範例中顯示,因此你可以看到兩種方法。

匿名函數

JavaScript 和 Scala 都允許你定義匿名函數,你可以將它們傳遞到其他函數和方法中。

箭頭函數和匿名函數

// 箭頭函數
let log = (s) => console.log(s)

// 匿名函數
let log = function(s) {
  console.log(s);
}

// 在這裡使用其中任何一個函數
function printA(a, log) {
  log(a);
}
// 函數(指派給變數的匿名函數)
val log = (s: String) => console.log(s)

// scala 方法。方法往往更常使用,
// 可能因為它們更容易閱讀。
def log(a: Any) = console.log(a)

// 函數或方法可以傳遞到另一個
// 函數或方法
def printA(a: Any, f: log: Any => Unit) = log(a)

在 Scala 中,你很少使用顯示的第一個語法定義函數。相反,你通常在使用點定義匿名函數。許多集合方法是 高階函數,並接受函數參數,因此你可以撰寫類似這樣的程式碼

// map method, long form
List(1,2,3).map(i => i * 10)   // List(10,20,30)

// map, short form (which is more commonly used)
List(1,2,3).map(_ * 10)        // List(10,20,30)

// filter, short form
List(1,2,3).filter(_ < 3)      // List(1,2)

// filter and then map
List(1,2,3,4,5).filter(_ < 3).map(_ * 10)   // List(10, 20)

類別

Scala 同時具有類別和案例類別。類別類似於 JavaScript 類別,通常用於 OOP 風格應用程式(儘管它們也可以用於 FP 程式碼),而案例類別具有其他功能,使其在 FP 風格應用程式 中非常有用。

下列範例顯示如何建立多種類型作為列舉,然後定義 OOP 風格的 Pizza 類別。最後,建立一個 Pizza 實例並使用它

// create some enumerations that the Pizza class will use
enum CrustSize:
  case Small, Medium, Large

enum CrustType:
  case Thin, Thick, Regular

enum Topping:
  case Cheese, Pepperoni, BlackOlives, GreenOlives, Onions

// import those enumerations and the ArrayBuffer,
// so the Pizza class can use them
import CrustSize.*
import CrustType.*
import Topping.*
import scala.collection.mutable.ArrayBuffer

// define an OOP style Pizza class
class Pizza(
  var crustSize: CrustSize,
  var crustType: CrustType
):

  private val toppings = ArrayBuffer[Topping]()

  def addTopping(t: Topping): Unit =
    toppings += t

  def removeTopping(t: Topping): Unit =
    toppings -= t

  def removeAllToppings(): Unit =
    toppings.clear()

  override def toString(): String =
    s"""
      |Pizza:
      |  Crust Size: ${crustSize}
      |  Crust Type: ${crustType}
      |  Toppings:   ${toppings}
    """.stripMargin

end Pizza

// create a Pizza instance
val p = Pizza(Small, Thin)

// change the crust
p.crustSize = Large
p.crustType = Thick

// add and remove toppings
p.addTopping(Cheese)
p.addTopping(Pepperoni)
p.addTopping(BlackOlives)
p.removeTopping(Pepperoni)

// print the pizza, which uses its `toString` method
println(p)

介面、特質和繼承

Scala 使用特質作為介面,也用於建立混入。特質可以同時具有抽象和具體成員,包括方法和欄位。

此範例顯示如何定義兩個特質,建立一個擴充和實作這些特質的類別,然後建立和使用該類別的實例

trait HasLegs:
  def numLegs: Int
  def walk(): Unit
  def stop() = println("Stopped walking")

trait HasTail:
  def wagTail(): Unit
  def stopTail(): Unit

class Dog(var name: String) extends HasLegs, HasTail:
  val numLegs = 4
  def walk() = println("I’m walking")
  def wagTail() = println("⎞⎜⎛  ⎞⎜⎛")
  def stopTail() = println("Tail is stopped")
  override def toString = s"$name is a Dog"

// create a Dog instance
val d = Dog("Rover")

// use the class’s attributes and behaviors
println(d.numLegs)   // 4
d.wagTail()          // "⎞⎜⎛  ⎞⎜⎛"
d.walk()             // "I’m walking"

控制結構

除了 JavaScript 中使用 ===!== 之外,JavaScript 和 Scala 中的比較和邏輯運算子幾乎相同。

比較運算子

JavaScript Scala
== ==
=== ==
!= !=
!== !=
> >
< <
>= >=
<= <=

邏輯運算子

JavaScript Scala
&&
||
!
&&
||
!

if/then/else 表達式

JavaScript 和 Scala 的 if/then/else 陳述式類似。在 Scala 2 中,它們幾乎相同,但在 Scala 3 中,不再需要大括號(儘管仍然可以使用)。

if 陳述式,一行

if (x == 1) { console.log(1); }
if x == 1 then println(x)

if 陳述式,多行

if (x == 1) {
  console.log("x 是 1,正如你所見:")
  console.log(x)
}
if x == 1 then
  println("x 是 1,正如你所見:")
  println(x)

if、else if、else

if (x < 0) {
  console.log("負數")
} else if (x == 0) {
  console.log("零")
} else {
  console.log("正數")
}
if x < 0 then
  println("負數")
else if x == 0
  println("零")
else
  println("正數")

if 傳回值

JavaScript 使用三元運算子,而 Scala 則照常使用其 if 表達式

let minVal = a < b ? a : b;
val minValue = if a < b then a else b

if 作為方法主體

Scala 方法傾向於非常簡短,而且你可以輕鬆地使用 if 作為方法主體

function min(a, b) {
  return (a < b) ? a : b;
}
def min(a: Int, b: Int): Int =
  if a < b then a else b

在 Scala 3 中,如果你願意,仍然可以使用「大括號」樣式。例如,你可以這樣撰寫 if/else-if/else 表達式

if (i == 0) {
  println(0)
} else if (i == 1) {
  println(1)
} else {
  println("other")
}

迴圈

JavaScript 和 Scala 都具有 while 迴圈和 for 迴圈。Scala 以前有 do/while 迴圈,但它們已從語言中移除。

while 迴圈

let i = 0;
while (i < 3) {
  console.log(i);
  i++;
}
var i = 0;
while i < 3 do
  println(i)
  i += 1

如果您偏好,Scala 程式碼也可以寫成這樣

var i = 0
while (i < 3) {
  println(i)
  i += 1
}

下列範例顯示 JavaScript 和 Scala 中的 for 迴圈。它們假設您有下列集合可以使用

// JavaScript
let nums = [1, 2, 3];

// Scala
val nums = List(1, 2, 3)

for 迴圈,單行

// 較新的語法
for (let i of nums) {
  console.log(i);
}

// 較舊的
for (i=0; i<nums.length; i++) {
  console.log(nums[i]);
}
// 偏好的
for i <- ints do println(i)

// 也可用
for (i <- ints) println(i)

for 迴圈,主體中有多行

// 偏好的
for (let i of nums) {
  let j = i * 2;
  console.log(j);
}

// 也可用
for (i=0; i<nums.length; i++) {
  let j = nums[i] * 2;
  console.log(j);
}
// 偏好的
for i <- ints do
  val i = i * 2
  println(j)

// 也可用
for (i <- nums) {
  val j = i * 2
  println(j)
}

for 迴圈中有多個產生器

let str = "ab";
for (let i = 1; i < 3; i++) {
  for (var j = 0; j < str.length; j++) {
    for (let k = 1; k < 11; k++) {
      let c = str.charAt(j);
      console.log(`i: ${i} j: ${c} k: ${k}`);
    }
  }
}
for
  i <- 1 to 2
  j <- 'a' to 'b'
  k <- 1 to 10 by 5
do
  println(s"i: $i, j: $j, k: $k")

帶有防護的產生器

防護for 表達式內 if 表達式的名稱。

for (let i = 0; i < 10; i++) {
  if (i % 2 == 0 && i < 5) {
    console.log(i);
  }
}
for
  i <- 1 到 10
  if i % 2 == 0
  if i < 5
do
  println(i)

for 理解

for 理解是使用 yield 傳回 (產生) 值的 for 迴圈。它們常在 Scala 中使用。

不適用
val list =
  for
    i <- 1 到 3
  yield
    i * 10
// 結果:Vector(10, 20, 30)

switch 和 match

JavaScript 有 switch 陳述式,Scala 則有 match 表達式。與 Scala 中的其他所有事物一樣,它們確實是表達式,表示它們會傳回結果

val day = 1

// later in the code ...
val monthAsString = day match
  case 1 => "January"
  case 2 => "February"
  case _ => "Other"

match 表達式可以在每個 case 陳述式中處理多個比對。

val numAsString = i match
  case 1 | 3 | 5 | 7 | 9 => "odd"
  case 2 | 4 | 6 | 8 | 10 => "even"
  case _ => "too big"

它們也可以用作方法的主體

def isTruthy(a: Matchable) = a match
  case 0 | "" => false
  case _ => true

def isPerson(x: Matchable): Boolean = x match
  case p: Person => true
  case _ => false

match 表達式有許多其他模式比對選項。

集合類別

Scala 有不同的 集合類別 來滿足不同的需求。

常見的不可變序列為

  • 清單
  • 向量

常見的可變序列為

  • 陣列
  • 陣列緩衝區

Scala 也有可變和不可變的對應和集合。

以下是建立常見 Scala 集合類型的步驟

val strings = List("a", "b", "c")
val strings = Vector("a", "b", "c")
val strings = ArrayBuffer("a", "b", "c")

val set = Set("a", "b", "a") // result: Set("a", "b")
val map = Map(
  "a" -> 1,
  "b" -> 2,
  "c" -> 3
)

集合方法

以下範例展示許多使用 Scala 集合的不同方式。

填充清單

// to, until
(1 to 5).toList                   // List(1, 2, 3, 4, 5)
(1 until 5).toList                // List(1, 2, 3, 4)

(1 to 10 by 2).toList             // List(1, 3, 5, 7, 9)
(1 until 10 by 2).toList          // List(1, 3, 5, 7, 9)
(1 to 10).by(2).toList            // List(1, 3, 5, 7, 9)

('d' to 'h').toList               // List(d, e, f, g, h)
('d' until 'h').toList            // List(d, e, f, g)
('a' to 'f').by(2).toList         // List(a, c, e)

// range method
List.range(1, 3)                  // List(1, 2)
List.range(1, 6, 2)               // List(1, 3, 5)

List.fill(3)("foo")               // List(foo, foo, foo)
List.tabulate(3)(n => n * n)      // List(0, 1, 4)
List.tabulate(4)(n => n * n)      // List(0, 1, 4, 9)

序列函數方法

// these examples use a List, but they’re the same with Vector
val a = List(10, 20, 30, 40, 10)      // List(10, 20, 30, 40, 10)
a.contains(20)                        // true
a.distinct                            // List(10, 20, 30, 40)
a.drop(2)                             // List(30, 40, 10)
a.dropRight(2)                        // List(10, 20, 30)
a.dropWhile(_ < 25)                   // List(30, 40, 10)
a.filter(_ < 25)                      // List(10, 20, 10)
a.filter(_ > 100)                     // List()
a.find(_ > 20)                        // Some(30)
a.head                                // 10
a.headOption                          // Some(10)
a.init                                // List(10, 20, 30, 40)
a.last                                // 10
a.lastOption                          // Some(10)
a.slice(2,4)                          // List(30, 40)
a.tail                                // List(20, 30, 40, 10)
a.take(3)                             // List(10, 20, 30)
a.takeRight(2)                        // List(40, 10)
a.takeWhile(_ < 30)                   // List(10, 20)

// map, flatMap
val fruits = List("apple", "pear")
fruits.map(_.toUpperCase)             // List(APPLE, PEAR)
fruits.flatMap(_.toUpperCase)         // List(A, P, P, L, E, P, E, A, R)

val nums = List(10, 5, 8, 1, 7)
nums.sorted                           // List(1, 5, 7, 8, 10)
nums.sortWith(_ < _)                  // List(1, 5, 7, 8, 10)
nums.sortWith(_ > _)                  // List(10, 8, 7, 5, 1)

List(1,2,3).updated(0,10)             // List(10, 2, 3)
List(2,4).union(List(1,3))            // List(2, 4, 1, 3)

// zip
val women = List("Wilma", "Betty")    // List(Wilma, Betty)
val men = List("Fred", "Barney")      // List(Fred, Barney)
val couples = women.zip(men)          // List((Wilma,Fred), (Betty,Barney))

Scala 有許多其他可供你使用的函數方法。所有這些函數方法的優點如下:

  • 你不需要撰寫自訂 for 迴圈來解決問題
  • 當你閱讀別人的程式碼時,你不需要閱讀他們的自訂 for 迴圈;你只要找到像這些的常見函數方法即可,因此可以更輕鬆地閱讀不同專案的程式碼

元組

當你想要將多個資料類型放入同一個清單時,JavaScript 讓你這樣做

let stuff = ["Joe", 42, 1.0];

在 Scala 中,你這樣做

val a = ("eleven")
val b = ("eleven", 11)
val c = ("eleven", 11, 11.0)
val d = ("eleven", 11, 11.0, Person("Eleven"))

在 Scala 中,這些類型稱為元組,如所示,它們可以包含一個或多個元素,而且元素可以有不同的類型。你存取它們的元素的方式就像存取 ListVectorArray 的元素一樣

d(0)   // "eleven"
d(1)   // 11

列舉

JavaScript 沒有列舉,但你可以這樣做

let Color = {
  RED: 1,
  GREEN: 2,
  BLUE: 3
};
Object.freeze(Color);

在 Scala 3 中,你可以使用列舉執行許多事情。你可以建立等同於該程式碼的程式碼

enum Color:
  case Red, Green, Blue

你可以建立參數化列舉

enum Color(val rgb: Int):
  case Red   extends Color(0xFF0000)
  case Green extends Color(0x00FF00)
  case Blue  extends Color(0x0000FF)

你也可以建立使用者定義的列舉成員

enum Planet(mass: Double, radius: Double):
  case Mercury extends Planet(3.303e+23, 2.4397e6)
  case Venus   extends Planet(4.869e+24,6.0518e6)
  case Earth   extends Planet(5.976e+24,6.37814e6)
  // more planets here ...

  private final val G = 6.67300E-11
  def surfaceGravity = G * mass / (radius * radius)
  def surfaceWeight(otherMass: Double) = otherMass * surfaceGravity

Scala.js DOM 程式碼

Scala.js 讓你撰寫 Scala 程式碼,並編譯成 JavaScript 程式碼,然後可以在瀏覽器中使用。此方法類似於 TypeScript、ReScript 和其他編譯成 JavaScript 的語言。

包含必要的函式庫,並匯入專案中必要的套件後,撰寫 Scala.js 程式碼看起來與撰寫 JavaScript 程式碼非常類似

// show an alert dialog on a button click
jQuery("#hello-button").click{() =>
  dom.window.alert("Hello, world")
}

// define a button and what should happen when it’s clicked
val btn = button(
  "Click me",
  onclick := { () =>
    dom.window.alert("Hello, world")
  })

// create two divs with css classes, an h2 element, and the button
val content =
  div(cls := "foo",
    div(cls := "bar",
      h2("Hello"),
      btn
    )
  )

// add the content to the DOM
val root = dom.document.getElementById("root")
root.innerHTML = ""
root.appendChild(content.render)

請注意,儘管 Scala 是類型安全的語言,但上述程式碼中並未宣告任何類型。Scala 強大的類型推論功能通常會讓 Scala 程式碼看起來像是動態類型。但它具有類型安全性,因此您可以在開發週期早期就捕捉到許多類型的錯誤。

其他 Scala.js 資源

Scala.js 網站有許多教學課程,專為有興趣使用 Scala.js 的 JavaScript 開發人員設計。以下是其中一些入門教學課程

Scala 中獨有的概念

Scala 中還有其他目前在 JavaScript 中沒有等效項的概念

  • 幾乎所有與 情境抽象 相關的內容
  • 方法功能
    • 多個參數清單
    • 呼叫方法時使用命名參數
  • 將特質用作介面
  • 案例類別
  • 伴隨類別和物件
  • 建立自己的 控制結構 和 DSL 的能力
  • match 表達式和模式比對的進階功能
  • for 綜合
  • 中綴方法
  • 巨集和元程式設計
  • 更多 …

此頁面的貢獻者