Dart JS TS 的用法語法比較

20 回覆
7 Like 5 Dislike
2019-02-20 10:06:51
隨著Flutter受到開發者的重視,Google於2011年推出的Dart又重新進入大家關注的視野之內,不過除了Flutter以外,其實Google的開發者早在2016年也推出過Angular Dart,讓開發者以Dart開發網站應用,不過由於Angular Dart對比TypeScript版Angular文本長期不足,因此沒有引起太多關注。Google推出Flutter,可以說為大家對Dart的信心注入了一劑强心針,大家又重新開始關注這個已有8年歷史的程式語言。

本文想介紹的是,就是到底Dart有何特色?與JavaScript比較,又有何優劣?由於TypeScript開始於前端日漸盛行,我們亦可以趁機比較一下三種語言的異同。




應用範圍(Application)

有讀過上一篇Web Technology為何征服世界的朋友,應該已經知道JavaScriptTypeScript已經可以在網頁、伺服器、智能電話、IOT、人工智能等範疇落地生根,Dart呢?托Flutter的發展,Dart已相當適合同時於網頁、伺服器、智能電話等範圍作開發,這一點與JavaScript已不相上下。不過DartJavaScript的最大分別,在於Dart本身可以有三種方法運行:分別是編譯為JavaScript(Compiled To JavaScript)、由Dart VM獨立運行(Standalone By Dart VM)、AOT編譯為機械碼(Ahead-of-time compiled to machine code). 而JavaScript現時最流行的做法,都是以Node運行JavaScript。Node運行JavaScript時,會將JavaScript轉變為機械碼(Machine Code),再運行機械碼。亦是因此Node JS的運行速度比其他動態語言如Python、Ruby等都較快。而Flutter所採用的,就是第三種方法,先編譯為機械碼(AOT Compilation)再在智能電話運行,因此大家可能聽過Flutter無需JS Bridge的原因,亦是由於早已編譯為機械碼,所以無需一個額外的JS Bridge再作轉譯。

React Native寫成的手機程式結構如下:



Flutter寫成的手機程式結講則如下:



Source (https://hackernoon.com/whats-revolutionary-about-flutter-946915b09514)

基本運行

理解了Dart、JavaScript、TypeScript各自的應用範圍,就以三種語言都寫一個簡單的hello world為例:

JavaScript 和 TypeScript的例子都是:
console.log("Hello World");

Dart的例子:
print("Hello World");

要在command line運行,就分別如下面三行:
node index.js
ts-node index.ts
dart main.dart

以上index.jsindex.tsmain.dart都是進入點(entry point)。

具體分別不大,都是以語言的命令(node,ts-node,dart)直接運行檔案,無須額外編譯,因為Dart受JavaScript 影響很大,想必也從JavaScript汲取了這一點。

順帶一提,JS及TS都支援REPL(Read-Eval-Print-Loop),但Dart無官方REPL,無法像JS及TS一樣於REPL裏面直接嘗試代碼。
2019-02-20 10:07:37
基本語法

基本語法上,由於Dart受JavaScript影響很大,因此語法上很類似,但與TypeScript比較之下,卻看見了兩者取態的不同。TypeScript受Scala的語法影響,將類別(Type)置於變數及參數之後;相反,Dart則沿用傳統Java及C#的前置類別語法。

由變數及函數一看,就可見不同之處。

變數(Variable)

JavaScript例子:
var num = 123;
let hello = "Hello Dart!";
const obj = { key1: 1234, key2: 5678};

TypeScript例子(例子中類別皆可省略):
var num:number = 123;
let hello:string = "Hello Dart!";
const obj:obj = { key1: 1234, key2: 5678};

Dart例子:
var num = 42;
dynamic hello = "Hello Dart!";
final obj = {"key1":1234,"key":5678};
hello = 1234;
String myName = "Tecky";
const PI = 3.141592654;
var x; // == null

JavaScript的例子與TypeScript除了額外的類別,幾乎一模一樣,反之Dart則非常不同,Dart有幾種不同的方法定義變數:

.var: 定義一個新的變數,類別由數值所推論,所以如果將num重新賦值為String會出現Error,但賦值為同一類別則無問題。
.dynamic: 定義一個新的變數,類別不定,重新賦值任何類別都無問題。
.final: 定義一個新的常數,不可重新賦值。
.直接前置類別如String: 定義一個新的變數,類別由前置類別決定,如果將重新賦值為其他類別會出現Error,但賦值為同一類別則無問題
.const: 與final類似,編譯常數,不可重新賦值。


可見Dart為了增强JavaScript類別上的欠缺,特意下了不少功夫,也解決了varlet之分,可是相較起來,似乎TypeScript的後置類別更為簡潔。

運算符號(Operators)

運算符號上,Dart跟JavaScript及TypeScript都很類似,其中一個最大的分別,在於Dart不支援===,而且在if statement中,必須使用boolean,不可以如JS及TS一樣使用其他數值作boolean使用。

JavaScript 及TypeScript例子:
let num = null;
if (!num) {
  console.log(`null is false`);
}
let zero = 0;
if (!zero) {
  console.log(`zero is false`);
}

以上用法在Dart是錯誤。只能使用Boolean作真假判斷
Dart例子:
var num = null;
if(num == null){
  print(`null is not false`);
}
var zero = 0;
if(zero == 0){
  print(`zero is not false`);
}

函數(Function)

函數方面,Dart不使用關鍵字function,語法較簡潔。

JavaScript例子:

function sum(a,b){
  return a + b;
}

TypeScript例子(例子中回傳值的類別可省略):
function sum(a:number,b:number):number{
  return a + b;
}

Dart例子:
sum(int a, int b){
  return a+b;
}

Dart的例子中,如果不寫int的類別,那兩個參數都會是dynamic 類別,也就是任何類別都可以成為參數。
sum(a,b){
  return a+b;
}
// equals to

sum(dynamic a,dynamic b){
  return a+b;
}

而如果你寫了
sum("1",1);

就會出現一個Runtime Exception,也就是與JavaScript類似,失去了類別的保護作用。
似乎dynamic就是dartany吧。

而且dart還有一個特點,就是每個作為進入點的檔案都必須有一個名為main的函數作為進入點,這一點明顯繼承了C的傳統
main(){
  sum(2,2);
}

sum(int a, int b){
  return a+b;
}
2019-02-20 10:08:40
進階語法

除了以上基本函數、運算符號、變數的語法之外,Dart作為一種多用途語言,亦同時有類別(Class)的語法及專為非同步編程(Async Programming)而設的語法。

類別(Class)

類別是物件導向編程一個重要部份,Dart由JavaScript發展出來,因此類別語法亦與JavaScript非常類似,卻又與TypeScript有些相似。

以下是Dart的類別語法:
import 'dart:math';

class Point{
  num x;
  num y;
  num z= 0;

  Point(num x, num y){
    this.x = x;
    this.y = y;
  }

  num distanceTo(Point other) {
    var dx = x - other.x;
    var dy = y - other.y;
    return sqrt(dx * dx + dy * dy);
  }
}

void main(){
  var p1 = Point(2,2);
  var p2 = new Point(4,5);
  p1.distanceTo(p2);
}

與JavaScript相當類似,不同在於method 上定義的分別及初始化(initialization)物件不一定需要new keyword.

以下是TypeScript同樣的類別語法:
class Point{

  private x: number;
  private y: number;
  private z: number = 0;

  constructor(x:number,y:number){
    this.x = x;
    this.y = y;
  }

  distanceTo(Point other){
    let dx = x - other.x;
    let dy = y - other.y;
    return sqrt(dx * dx + dy * dy);
  }
}

const p1 = new Point(2,2);
const p2 = new Point(4,5);
p1.distanceTo(p2);

要留意的是,Dart亦不支援Access Modifier,例如上面TypeScript所用的private在Dart裏面不會用到。因此Dart不能像
TypeScript一樣,定義private field.

非同步編程(Asynchronous Programming)

作為前端開發的程式語言,非同步編程是必不可少的一部份,汲取了JavaScript的教訓,Dart本身就支援了async

Dart的async與JavaScript幾乎一模一樣,分別只是先後次序寫法,以及必須寫下傳回值的類別,也就是Future
Future的概念與JavaScript Promise無任何分別,只是名字上的分別。Java的非同步編程類別,也是稱為Future
Future main() async{
  await someAsyncOperation();
}

以下就是JavaScript的版本
async function main(){
  await someAsyncOperation()
}

總結

本文總結了一些DartJavaScriptTypeScript的異同,亦因篇幅所限,未能詳盡解釋其他Dart特別用法例如MixinsCallable Classes等。筆者認為Dart明顯是希望改善JavaScript弱類別的缺點而設計,然而Dart卻因為多年的停滯錯過了前端近年的飛速發展,反而被後上的TypeScript超越。程式語言的受歡迎程度,往往可以受一兩個應用範圍所左右:Objective-C一直寂寂無名,因為iOS的發展變得廣受歡迎;RustFirefox自家製程式語言,也因為Firefox新引擎Servo而變得聲名大噪,未知Flutter能否為Dart迎來發展之第二春呢?這就要大家拭目以待了。
2019-02-20 10:10:41
P.S.: 最近連登 update 左做 WYSIWYG edtior,但 copy & paste 野去連登個 text editor 時會 trim 走咗啲 leading spaces要人手做 indentation,邊度有得 file bug report 啊?
2019-02-20 12:09:54
學Dart把鬼
陣間google又唔support又中大伏
2019-02-20 12:12:34
好同意 Google 嘅往績真係好伏
但如果 Flutter 真係贏 React Native,咁可能到時真係要學 Dart
2019-02-20 12:18:08
到時再算啦
2019-02-20 15:11:19
當你識JS好難唔識Dart
只係少少syntax difference
如果你覺得dart都要學
即係你唔係Google TA
返去用RN啦
2019-02-20 15:41:31
始終接受唔到 dart 唔跟 es7 and beyond
2019-02-20 15:52:13
到時google唔放棄flutter/dart再算啦
2019-02-20 16:42:25
on9
2019-02-20 16:45:04
巴打 我留意左你好耐
你真係好幽默
我自問都算個ok幽默既人 但係你幽默感比我真係高十幾二十倍
錯 應該係100倍先岩
估唔到我係呢個post竟然見識到你既威力
我真係笑到爆左肚 依家一路打字一路撿返d腸呀內臟呀腎呀
塞返落個肚到
你有冇諗過未來幾個月去紅館開棟篤笑?





係咩驅使你咁得閒每個 post 都留下一句 on9?
2019-02-20 16:47:18
Why so serious?
學緊呢位巴打姐
https://lih.kg/cjaBgT
2019-02-20 19:37:05

感謝巴打幫忙一推
2019-02-20 22:24:16
邊有咁多如果
2019-02-21 08:09:22
"轉變為機械碼(Machine Code),再運行機械碼"
依句嘢好misleading,冇code可以唔轉machine language就run, nodejs快嘅原因係因為jit compiler,CPython完全冇

PyPy某啲benchmark其中比得上node,但係問題係所有CPython C interface嘅library會用唔到

另外啲styling
2019-02-21 09:20:07
要留意的是,Dart亦不支援Access Modifier,例如上面TypeScript所用的private在Dart裏面不會用到。因此Dart不能像
TypeScript一樣,定義private field.
Dart嘅private唔係_咩?
2019-03-01 15:19:10
見到上面有巴打講 js -> dart, 其實唔太似, dart其實更加似既java.

舉一個最接近既例子, 就係declare variable
//es6 + ts const value : int = 5 ; //swift let value : int = 5 ; //kotlin val value:Int =5 ;

dart
var value = 5 ; 
int num = 10;
final int value = 5 ; 


另外一個就係declare method / function

//es6 + ts 
foo () : int {} 

//swift 
func isToTheRightOf(x: Double) -> Bool ; 

//kotlin 
fun double(x: Int): Int ; 


//dart
int value () {
    return 5 ; 
}
2019-06-04 11:17:16
提外話
玩過下js基本既dom
可唔可以學react?
2019-06-04 12:44:25
如果掌握 JS DOM 有一定程度,當然可以再上 React 不過小心網上 React 文章多而雜亂,有啲用緊舊 version 黎寫,而某啲寫法而家已經係唔建議寫 (例如 componentWillMount)
吹水台自選台熱 門最 新手機台時事台政事台World體育台娛樂台動漫台Apps台遊戲台影視台講故台健康台感情台家庭台潮流台美容台上班台財經台房屋台飲食台旅遊台學術台校園台汽車台音樂台創意台硬件台電器台攝影台玩具台寵物台軟件台活動台電訊台直播台站務台黑 洞