【问题标题】:TypeScript closures - an "almost" solutionTypeScript 闭包——“几乎”的解决方案
【发布时间】:2015-06-18 00:53:59
【问题描述】:

TypeScript 最大的问题之一是它会将所有方法(无论访问修饰符如何)编译到原型中。

示例

class Example {
    public getString(): string {
        return "Hello World";
    }

    private getNumber(): number {
        return 123;
    }
}

我们知道,访问修饰符只在编译时检查,因此被发出的 JavaScript 忽略。 JavaScript 开发人员学会缓解这种情况的一种方法是使用闭包(好吧,我们知道使用闭包会降低性能,但我相信在某些情况下闭包是绝对必要的)。

示例

var Example = (function () {
    function Example() {
        this.getString = function () {
            return "Hello World";
        }

        var getNumber = function() {
            return 123;
        }
    }

    return Example;
})();

上面的例子尊重公共/私人访问。

我发现通过使用 lambda 语法,我们可以在 TypeScript 中声明公共闭包方法。

示例

class Example {
    getString = (): string => {
        return "Hello World";
    }
}

它不是特别漂亮,但它确实有效。

我想知道的是:如何在 TypeScript 中声明私有闭包?

示例

class Example {

    // TypeScript doesn't like this!
    var getNumber = (): number => {
        return 123;
    }
}

在此处查看有关此 bugbear 的更多信息:https://github.com/Microsoft/TypeScript/issues/2940

【问题讨论】:

  • 这对我来说似乎不是问题。您不能在 typescript 的其他类中使用私有函数,那么为什么这会困扰您呢?您是否试图向将在控制台中调查对象方法的 JS 开发人员隐藏这些功能?如果是这样,只需在它们前面加上下划线,如果他们使用这些功能,那是他们自己的错。
  • @DavidSherret 你明白我的意思。我想我来自经典的 OOP,您应该提供正确级别的方法访问权限,以便第 3 方开发人员确切知道他们能/不能做什么。我希望我可以用 JavaScript 干净地做到这一点,但唯一真正的解决方案是使用闭包。我不喜欢某种语言是私有的,然后在它编译的那一刻就公开的想法。虽然我理解 TypeScript 在这方面的动机,但我仍然认为 TypeScript 无法创建基于闭包的类是一个限制。
  • @DavidSherret - 另外,你说得对,如果他们使用不适合他们使用的功能,那是另一个开发人员的错,但我宁愿得到回应“你已经编写了一个防弹 API”,而不是“由于您的 API 中有大量泄漏的抽象,它就像筛子一样泄漏!”
  • 如果它是一个将被 JS 开发人员使用的库,我绝对理解这种担忧——澄清一下,对于打字稿开发人员来说,这不是问题。就个人而言,我认为为了克服 JS 的限制而牺牲代码的清晰性和简单性是不值得的。使用underscore prefix 肯定不是完美的,但对我来说,干净简单的代码比完全阻止某人访问未记录的方法和属性更重要。
  • ...JS 在这方面很糟糕,但我同意 typescript 可以选择以这种方式编译代码会很好,尽管这可能需要做很多工作让他们实施:/

标签: javascript typescript closures


【解决方案1】:

TypeScript 为 ES6 带来了类型和访问器(并且它静态地检查两者)。 TypeScript 中的 class 关键字是 ES6 中的标准 class 关键字。 ES6 类中没有私有闭包。此语法在 ES6 中无效

class Example {
    var v = /* ... */; // invalid in ES6
}

如果你需要声明一个封装变量的闭包,你应该使用经典的 JavaScript 方式。我强烈建议利用 TS 接口:

interface NamedObject {
    getName(): string;
}

let createNamedObject = function (name = 'John'): NamedObject {
    return {
        getName: function () {
            return name;
        }
    };
};

let obj: NamedObject = createNamedObject();

如果你真的想用闭包创建类方法,你可以这样做:

class BadPerformance {
    public getName: () => string;

    constructor(name = 'John') {
        this.getName = () => {
            return name;
        };
    }
}

【讨论】:

  • 实际上,TypeScript 支持类属性提案 - 所以v = ... 在 TypeScript 中有效(无 var),在 ES 中这是当前 0 阶段提案等待 TC 输入。
  • @Tarh 有正确的答案。虽然你应该通过设置一个局部变量var privateName = name 来清理它,这样很明显这确实是私有的。然后返回privateName。有一些应该使用它的真实案例场景。在所有其他人中,使用由 typescript 标记为私有的公共方法。在构建时将整个生产构建(没有公共 API)包装在一个 clusure 中。
【解决方案2】:

我们知道,访问修饰符只在编译时检查,因此被发出的 JavaScript 忽略。

这是因为这种情况下的隐私是 API 对其他开发人员的隐私。如果您希望他们知道该方法是私有的 - 向他们提供 .d.ts 文件,以便他们的编辑者知道或不在 API 文档中记录它。

在 JavaScript 中,文档通常被视为 API。

我想知道的是:如何在 TypeScript 中声明私有闭包?

您可以在构造函数中创建函数,这些函数将在实例而不是原型上声明它们。这将允许您使用闭包 - 它也违反原型继承以及 TypeScript 和 JavaScript 的性质。

【讨论】:

    猜你喜欢
    • 2011-12-01
    • 1970-01-01
    • 2020-06-07
    • 2021-09-23
    • 1970-01-01
    • 1970-01-01
    • 2011-12-01
    • 2010-09-16
    • 1970-01-01
    相关资源
    最近更新 更多