资讯专栏INFORMATION COLUMN

JavaScript => TypeScript 类入门

geekidentity / 1657人阅读

摘要:静态属性静态方法目前支持静态方法表示,类属性及静态属性目前作为提案还未正式成为标准。在中,抽象类不能用来实例化对象,主要做为其它派生类的基类使用。不同于接口,抽象类可以包含成员的实现细节。中也是这样规定的抽象类不允许直接被实例化。

尝试重写

在此之前,通过《JavaScript => TypeScript 入门》已经掌握了类型声明的写法。原以为凭着那一条无往不利的规则,就可以开开心心的重写 JS 项目了。当我跃跃欲试去重写一个 JS 项目时,发现阻碍重重。

在投靠 TS 时,TypeScript 允许将 JS 渐进式的过渡到 TS:

一些简单的基本类型声明的填充,比如:number, :string, :string[] 等等;

将一些稍复杂的、暂时还未提炼好的结构声明为 any 类型;

改后缀为 .ts, 执行 tsc 编译。

但一个明显的问题是,一个 JS 文件中往往有很多模块依赖,意味着要把所有这些模块都重新做一次类型声明,才能整体编译通过。

所以,要想畅通无阻的重写 JS,在上一篇入门的基础上,还得强忍着冲动,继续学习两部分内容:

1、TS 类的写法、特征
2、TS 模块、命名空间

好在,它们和 ES6 其实有着很多重合的地方——要记得,TS 是 ES6 的超集。所以如果掌握了 ES6,我们只要挑差异,找增量,进行迁移学习,就能快速掌握上述内容。

ES6 的类

ES6 的类的概念,和普遍编程语言的类概念一致,表示一种特有的数据结构。它既像一个函数(能被 new 调用),又像一个对象(包含了各种属性、方法)。

class MyClass {
  constructor() {
    this.attr = "my attribute";
  }
  foo(name) {
    console.log("hello " +  name);
  }
}
let myclass = new MyClass();

类中的方法属性被称为 “成员”,这些成员大概被分成 3 种类别:

公有属性、公有方法

私有属性、私有方法

静态属性、静态方法

在写继承时,我们并不希望在所有时候,这些属性、方法都被继承到子类;在访问成员时,也不希望在任何时候,类实例的所有成员都无一例外可以被访问;有时候我们希望与此相反,这样能保持开放出去的信息简洁干净。

JS 很早就有这些概念,但到现在为止,ES6 并没有处理好这个事情。

私有属性、私有方法

ES6 没有直观的表示私有属性、私有方法的方案,只能通过变通的方式间接地表示。

const getKeys = Symbol("getKeys_");
const attr = Symbol("attr_");
class MyClass {
  constructor() {
    // 私有属性
    this[attr] = "private attribute";
  }
  // 公有方法
  foo(config) {
    return this[fn](config);
  }
  // 私有方法
  [getKeys](config) {
    return Object.keys(config);
  }
};

这仅仅是一个间接取巧的方式避免直接被访问到,但很轻易就能绕过它:

let myclass = new MyClass();

let symbolsAttr = Object.getOwnPropertySymbols(myclass);
let attr_ = myclass[symbolsAttr[0]]; // 即访问到私有属性

let symbolsFn = Object.getOwnPropertySymbols(myclass.__proto__);
let getKeys_ = myclass[symbolsFn[0]]; // 即访问到私有方法

私有方法、私有属性的目的是不想开放过多的信息到外部。上面变通的方案虽然表面上达到了目的,但是不够直观,也不安全。

静态属性、静态方法

ES6 目前支持静态方法表示,类属性及静态属性目前作为提案还未正式成为标准。

class MyClass {
  name = "jeremy";  // ES6 不被支持,仅作为提案
  static version = "1.0.0"; // ES6 不被支持,仅作为提案
  constructor() {
    console.log(MyClass.version); // "1.0.0"
  }
  static get Version() {
    return MyClass.version;
  }
}

区分这些成员身份,与动态类型、静态类型语言没有必然联系,可以预见,在不久的将来,ES6 这方面将得到完善。

TS 的类

鉴于 TS 是 ES6 的超集这一事实,TS 类当然也有私有属性、私有方法静态属性、静态方法等这些身份的成员。在标记成员身份上,TS 与 Java 有很多相似之处。比如与继承相关的访问修饰符,以及其他限定作用的非访问修饰符

访问修饰符

private

public

protected

非访问修饰符

static

readonly

abstract

class User {
    readonly name: string;
    public age: number;
    private sex: string;
    protected marriage: string;
    constructor(name: string, sex: string) { 
        this.name = name;
        this.sex = sex;
    }
    showAge() {
        console.log(`${this.name}, age ${this.age}`);
    }
}
访问修饰符

1、当成员被标记成 private 时,它就不能在声明它的类的外部访问。
2、protected 修饰符与 private 修饰符的行为很相似,但有一点不同,protected 成员在派生类中仍然可以访问
3、被声明为 public 的类、方法、构造方法和接口能够被任何其他类访问。

class User {
    readonly name: string;
    public age: number;
    private sex: string;
    protected marriage: string;
    constructor(name: string, sex: string) { 
        this.name = name;
        this.sex = sex;
    }
    showAge() {
        console.log(this.age);
    }
}

let a = new User("jerry", "male");
console.log(a.sex); // 编译报错:私有属性不许在本类之外被访问
console.log(a.marriage); // 编译报错:私有属性不许在类之外被访问
a.name = "jeremy"; // 编译报错:只读属性不许再次被写入

访问修饰符主要用在继承的可访问性上,继承好比遗传,用基因类比理解它们就很有意思:

private 私有基因——本体有效,不会被继承,即子类中无法访问到

protected 被保护基因——保护血统纯正,只允许在继承体系中访问

public 公共基因——子类、其他类都能访问到

有了访问修饰符,每个成员都有扮演着与身份对应的角色,真正做到名副其实。

访问修饰符和非访问修饰符加起来有6个甚至更多,它们如何与类、接口一起搭配工作,考虑到组合情况非常多,此处不去细致的探究。可以参考 Java 的规则:

default (即缺省,什么也不写): 在同一包(等同于JS中的模块)内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。

private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)

public : 对所有类可见。使用对象:类、接口、变量、方法

protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。

当然更直观的方式是上代码 + 编译。TS 的编译工具有着非常友好、明确编译错误提示。

class Demo {
    static private showSelf() {}
}
// 编译错误提示
error TS1029: "private" modifier must precede "static" modifier.

当然,去查阅官方文档也是一个好办法。

非访问修饰符

非访问修饰符不关心可访问性,被它多带带标记的成员,在任何时候都能访问到。目前至少有这些:

static

get

set

readonly

abstract

从字面上看,不难理解它们的用途。这里和 ES6 差别较大的是 abstract

abstract 修饰符

abstract 修饰符用来定义抽象类和在抽象类内部定义抽象方法。

在 Java 中,抽象类不能用来实例化对象,主要做为其它派生类的基类使用。 不同于接口,抽象类可以包含成员的实现细节。

TS 中也是这样规定的:抽象类不允许直接被实例化。

还有一点很重要,抽象类中的抽象方法可以不包含具体实现,但必须在派生类中实现。

// 抽象类
abstract class User {
    readonly name: string;
    public age: number;
    private sex: string;
    protected marriage: string;
    constructor(name: string, sex: string) { 
        this.name = name;
        this.sex = sex;
    }
    showAge() {
        console.log(this.age);
    }
    // 抽象方法
    abstract showName(): void;
}

// let a = new User("jerry", "male"); // 编译报错: 抽象类不允许直接实例化

容易忽略的一个问题是,一个类中一旦出现抽象方法,那这个类整个应该被标记为 abstract

class UserA extends User {
    constructor(name: string, sex: string) {
        super(name, sex);
        // console.log(this.sex); // 编译报错:私有变量不能被访问
    }
    // 抽象方法必须要在子类中实现
    // 若无此方法,编译报错
    showName() {
       console.log(this.name); 
    }
}

基本上,对 TS 类只需要掌握这些,深入的部分自然在实践中继续领悟。

对了,还有模块、命名空间没有梳理。因为码文字的麻烦,只得留到后续再补。但是直接搬用 ES6 的模块import, export 就完全够用了。

So,这回真的去重写了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89951.html

相关文章

  • JavaScript => TypeScript 入门

    摘要:为了由简入繁,不妨将这些类型划分为基本类型复合类型。以下将渐进式的对的这些类型进行了解。实际上,有一种属性描述对象,是通过获取的。但无论如何,类型检查是可以排除大部分错误的。在函数的类型声明中,继续来巩固这条规则的写法。 几个月前把 ES6 的特性都过了一遍,收获颇丰。现在继续来看看 TypesScript(下文简称为 TS)。限于经验,本文一些总结如有不当,欢迎指正。 概述 官网有这...

    Tonny 评论0 收藏0
  • 教你用Vue渐进式搭建聊天室,从JavaScript=>TypeScript

    摘要:前言这个轮子已经有很多人造过了,为了不重复造轮子,我将本项目以三阶段实现大家可以在中的查看纯前端后端前端后端前端希望能给大家一个渐进学习的经验。 前言 Vue+Socket.io这个轮子已经有很多人造过了,为了不重复造轮子,我将本项目以三阶段实现(大家可以在github中的Releases查看): 纯前端(Vuex) 后端+前端(JavaScript) 后端+前端(TypeScrip...

    skinner 评论0 收藏0
  • TypeScript快速入门

    摘要:添加了可选的静态类型注意并不是强类型和基于类的面向对象编程。类类型接口示例接口更注重功能的设计,抽象类更注重结构内容的体现模块中引入了模块的概念,在中也支持模块的使用。 一:Typescript简介 维基百科: TypeScript是一种由微软开发的自由和开源的编程语言。它是JavaScript的一个严格超集,并添加了可选的静态类型和基于类的面向对象编程。C#的首席架构师以及Delp...

    moven_j 评论0 收藏0
  • TypeScript入门教程

    摘要:现在,出现了更多本身支持或者通过插件支持语法智能提示纠错甚至是内置编译器的文本编辑器和。 TypeScript是什么 TypeScript是JavaScript的一个超集 TypeScript需要编译为JavaScript才能运行(语法糖) TypeScript提供了类型系统,规范类似Java TypeScript提供了ES6的支持,也可以支持部分ES7草案的特性,不用担心TypeS...

    Dr_Noooo 评论0 收藏0
  • SegmentFault 技术周刊 Vol.40 - 2018,来学习一门新的编程语言吧!

    摘要:入门,第一个这是一门很新的语言,年前后正式公布,算起来是比较年轻的编程语言了,更重要的是它是面向程序员的函数式编程语言,它的代码运行在之上。它通过编辑类工具,带来了先进的编辑体验,增强了语言服务。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不觉已经到来了,总结过去的 2017,相信小伙们一定有很多收获...

    caspar 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<