资讯专栏INFORMATION COLUMN

ES6 / TypeScript / Babel / C# 中的 super(base)

RaoMeng / 985人阅读

摘要:今天看到写的中的和都错了,觉得很有意思,所以也研究了一下。但既然用,就是为了用它的静态检查,所以要充分关注编译错误提示。很遗憾,同样的错误。的正式名称是,即那么,现在来说说的结果。因此在我实际工作中遇到类似问题的概率非常低,不纠结

今天看到 @justjavac 写的《ES6 中的 this & super:babel 和 typescript 都错了》,觉得很有意思,所以也研究了一下。

借用 @justjavac 的示例代码,略做修改,然后在几种语言中跑了一下,结果

语言(版本) 输出1 输出2 输出3
ES6 3 undefined 3
Babel 2 undefined 2
TypeScript (?) 2 3 2
C# 3 3 3
Java 3 3 3

是的,我加入了 C# 和 Java 的运行结果,毕竟它们是真正的 OOP 语言。另外请注意到,我在 TypeScript 后面加了个问号 (?),因为实际上 TypeScript 虽然编译成了对应的 JS,但是转译过程中是会报错的:

index.ts (20,15): Only public and protected methods of the base class are accessible via the "super" keyword. (2340)
index.ts (22,27): Only public and protected methods of the base class are accessible via the "super" keyword. (2340)

下面,我从 C#/Java 说起

C# / Java

对于 C#/Java 这样的真正的 OOP 语言来说,super.xthis.x 其实是一个东西,因为在子类中没有重新定义这个成员 x。以 C# 代码为例

using System;
                    
public class Program
{
    public static void Main()
    {
        var t = new ColorPoint();
        t.test();
    }
}

class Point {
    public int x;
    
    protected void getValue() {
        Console.WriteLine(this.x);
    }
}

class ColorPoint : Point {
    public ColorPoint() {
        this.x = 2;
        base.x = 3;
        Console.WriteLine(this.x);
        Console.WriteLine(base.x);
    }

    public void test() {
        this.getValue();
    }
}

上面这段代码是为了与下面这段代码进行比较——假如我们在子类中重新定义 x 呢?

class ColorPoint : Point {
    public new int x;
    
    public ColorPoint() {
        this.x = 2;
        base.x = 3;
        Console.WriteLine(this.x);
        Console.WriteLine(base.x);
    }

    public void test() {
        this.getValue();
    }
}

它的输出是 233,为什么?

this.x2 好理解,super.x3 也好理解。而 getValue() 中实际取的是父类中的 x,似乎有点不好理解——

其实也不难理解,因为子类中重新定义了 x,它和父类中的 x 就不是同一个东西了,只是正好名称相同而已。

另一个方面来理解:子类中重新定义 x,而不是重载(也不可能重载字段,只有方法和属性可以重载),那么 getValue() 就不会顺着虚函数链去找到最近的一个定义,也就不会取到子类中的赋值。

TypeScript

在 TypeScript 的 Playground 中运行下面的代码确实可以得到 232

class Point {
    public x: number;

    protected getValue() {
        console.log(this.x);
    }
}

class ColorPoint extends Point {
    constructor() {
        super();
        this.x = 2;
        super.x = 3;
        console.log(this.x);
        console.log(super.x);
    }

    test() {
        this.getValue();
    }
}

const t = new ColorPoint();
t.test();

问题在于,不管是在 Playground 还是 VSCode 还是 vsc(编译器),都会得到错误提示

Only public and protected methods of the base class are accessible via the "super" keyword.

这里提到了用 super 的两个条件,一个是 publicprotected 修饰,二个是 methods。第二个条件就是关键所在:TypeScript 中只能通过 super 调用方法,所以 super.x 从语法上来说就是错的!我不知道 Anders Hejlsberg 为什么要在语法错误的情况仍然输出结果——也许是为了容错性。但既然用 TypeScript,就是为了用它的静态检查,所以要充分关注编译错误提示。

现在来试验一下介于 field 和 method 之间的情况,使用 getter/setter 语法的属性。

class Point {
    private _x: number;
    public get x(): number {
        return this._x;
    }

    public set x(value: number) {
        this._x = value;
    }

    protected getValue() {
        console.log(this.x);
    }
}

很遗憾,同样的错误。就这一点来说,我觉得 TypeScript 还有待进步。

ES6 / ES2015 / Babel
ES6 的正式名称是 ECMAScrip 2015,即 ES2015

那么,现在来说说 ES6 的结果 3undefined3

……

可是,我除了说不能理解之外,还能说什么呢?

既然 super.x = 3 都可以起作用,凭什么 console.log(super.x) 就取不到值?从这一点上来说,Babel 的结果 (2undefined2) 反而更符合逻辑。

小结

ES6 的结果我不能理解,也许能从 ECMAScript 2015 Language Specification 中找到答案,不过我没耐心去阅读这个长而枯燥的英文文档——如果有人找到了答案,麻烦告诉我一声,万分感谢!

不管怎么说,我用 TypeScript 的时间比较多,而且忠实于编译器的错误提示。因此在我实际工作中遇到类似问题的概率非常低,不纠结 ^_^

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

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

相关文章

  • 2019 简易Web开发指南

    摘要:工具软件欲先攻其事必先利其器,用好工具是做好开发的基础。框架目前最流行简单易用,越来越多人用曾经很流行,现在有点衰退状态管理后端渲染开发工具依赖管理,应用打包,任务管理,编辑器扩展,,移动端有了前端的知识后,我们还可以开发手机。 2019年即将到来,各位同学2018年辛苦了。 不管大家2018年过的怎么样,2019年还是要继续加油的! 在此我整理了个人认为在2019仍是或者将成为主流的...

    vspiders 评论0 收藏0
  • 深入学习TypeScript

    摘要:是的超级,遵循最新的规范相当于包含了的语法。表示方法没有返回任何类型类型表示的是那些永不存在的值的类型,例如异常错误写法错误三函数内容概述函数的定义可选参数默认参数剩余参数函数重载箭头函数。 一、Typescript 介绍、环境搭建 1.1 Typescript 介绍 1.TypeScript 是由微软开发的一款开源的编程语言,像后端 java、C#这样的面向对象语言可以让 js 开发...

    赵连江 评论0 收藏0
  • TypeScript 初识

    摘要:当你陷在一个中大型项目中时应用日趋成为常态,没有类型约束类型推断,总有种牵一发而动全身的危机和束缚。总体而言,这些付出相对于代码的健壮性和可维护性,都是值得的。目前主流的都为的开发提供了良好的支持,比如和。参考资料中文文档 文章博客地址:http://pinggod.com/2016/Typescript/ TypeScript 是 JavaScript 的超集,为 JavaScrip...

    iliyaku 评论0 收藏0
  • 从 JavaScript 到 TypeScript - 模块化和构建

    摘要:不过,相对于静态类型检查带来的好处,这些代价是值得的。当然少不了的模块化标准,虽然到目前为止和大部分浏览器都还不支持它。本身支持两种模块化方式,一种是对的模块的微小扩展,另一种是在发布之前本身模仿的命名空间。有一种情况例外。 TypeScript 带来的最大好处就是静态类型检查,所以在从 JavaScript 转向 TypeScript 之前,一定要认识到添加类型定义会带来额外的工作量...

    Jonathan Shieber 评论0 收藏0
  • [译] ES6 学习笔记:关于 ES2015 特性的详细概述

    摘要:将转换成常见的使用实现的基于迭代器的迭代。处停止迭代器基于鸭子模型接口这里使用语法仅仅为了说明问题使用支持为了使用迭代器属性需要引入。生成器是迭代器的子类,包含了附加的与。 原文地址:http://babeljs.io/docs/learn-...本文基于Luke Hoban精妙的文章《es6features》,请把star献给他,你可以在此尝试这些特性REPL。 概述 ECMAScr...

    leoperfect 评论0 收藏0

发表评论

0条评论

RaoMeng

|高级讲师

TA的文章

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