0

TS(JS)与 Go

 4 years ago
source link: https://studygolang.com/articles/26437
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

JavaScript 是一门解释型语言或即时编译型语言,在运行时通过编译生成二进制机器码,它的运行大致经过以下几个阶段(以 V8 引擎为例):

如果使用了 TypeScript,则在运行之前 TypeScript 将会编译成 JavaScript 代码。

Qv63uev.jpg!web

v8 引擎首先会解析源码,生成抽象语法树(AST),基于 AST,解释器便可以开始工作生成字节码,经过编译器后生成可以运行的机器码。

Go 是一门编译型语言,在代码***运行之前***需要通过编译器生成二进制机器码。它的编译过程大致如下:

Nzqi2qi.png!web

代码首先会被扫描(词法分析)生成 token,后经过 Parser(语法分析) 生成 AST,接着会有一个类型检查的阶段,通常叫做语义分析,生成中间代码,后经过优化处理后最终生成目标机器码。

静态类型

TypeScript 和 Go 都是静态类型语言。

对于 TypeScript,笔者时常看到有关于它的各种「骚操作」,比如从 A | B 得到 A & B

type UnionToIntersection<U> =
  (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never

interface A {
  name: string;
}

interface B {
  age: number;
}
type Res = UnionToIntersection<A | B>;  // A & B
复制代码

或者是:

type GetArrayMembers<T> = T extends {[index in keyof T]: infer V } ? V : never
const example = [1, 2, 3] as const;
type Members = GetArrayMembers<typeof example>; // 1, 2, 3
复制代码

这些「骚操作」,几乎很少有人第一眼就能完全明白其中的含义。甚至多少有点「秀的我脑壳疼」的感觉。

但是考虑到 TypeScript 定义为 JavaScript 的超级,类型系统设计的这么复杂也就不足为奇了,毕竟 JavaScript 是「怎么灵活怎么来」。

对于 Go 语言,在 1.x 版本中,它的静态类型经常被调侃成「大道至简」。其中缺少「 泛型 」一直被列为该语言需要修复的三大问题之一,探其原因,无非就是「这个需求我不接」之类的套路话了。不过好在在 2.0 版本中,Go 语言将会实现「泛型」这个功能。

此外,对于我们时常纠结「什么时候该用 interfacetype 」 的问题,Go 语言对此做了很好的限制,它使用了一个新的 struct ,而 interface 则被限制为一组抽象方法的集合:

package main;

import "fmt";

type Human struct {
	name string;
	age int;
	phone string;
}

// go 里方法(函数和方法不相同)
// Human 实现 SayHi 方法
func (h Human) SayHi() {
	fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone);
}


type Men interface {
	SayHi()
}

func main() {
	mike := Human{ "mike", 25, "137xxx"};

	var i Men;

	i = mike;
	i.SayHi();
}
复制代码

最后,在 TypeScrip 中,你可以使用 any 来规避编译器的类型检查,在 Go 中,可以使用空 interface 实现与此相似的作用:

let a: any = 1;
a = 'hello';
复制代码
var a interface{}
var i int = 5;
s := "Hello world";
a = i;
a = s;
复制代码

面向对象与继承

JavaScript 是一种基于原型继承的语言,自 ES6 发布以后,可以使用 classextends 等语法糖来替代以前繁琐的写法。TypeScript 在此基础上,扩展了类的能力,如添加 publicprivateprotected 等修饰符。

class AChild {
  protected name = 'hello world'
}

class PA extends AChild {
  say() {
    return this.name;
  }
}
复制代码

在 Go 语言中,由于没有构造函数,实现面向对象时,你需要这么写:

package main;

import "fmt";

type Human struct {
	name string;
	age int;
	phone string;
}

type Employ struct {
	Human; // 匿名字段
	company string;
}

// Human 实现 SayHi 方法
func (h Human) SayHi() {
	fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone);
}

// Human 实现 Sing 方法
func (h Human) Sing() {
	fmt.Printf("hahaha");
}

// Employee 重载 Human 的 SayHi 方法
func (e Employ) SayHi() {
	fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name, e.company, e.phone)
}

func main() {
	mike := Employ { Human { "mike", 25, "137xxx" }, "上海" };

	fmt.Printf("name: %s, age: %d. phone: %s, company: %s", mike.name, mike.age, mike.phone, mike.company); // name: mike, age: 25, phone: 137xxx. company: 上海
	mike.Sing();    // hahaha
	mike.SayHi();   // Hi, I am mike, I work at 千寻. Call me on 137xxx
}
复制代码

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK