简体   繁体   English

TypeScript闭包 - 一种“差不多”的解决方案

[英]TypeScript closures - an “almost” solution

One of my biggest bugbears with TypeScript is the fact that it compiles all methods (regardless of the access modifier) to the prototype. 我最大的一个关于TypeScript的问题是,它将原型的所有方法(无论访问修饰符)编译。

Example

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

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

As we know, the access modifiers are only checked at compilation, thus ignored by the emitted JavaScript. 众所周知,访问修饰符仅在编译时检查,因此被发出的JavaScript忽略。 One way JavaScript developers have learned to mitigate this is to use closures (okay, we know there are performance penalties to pay with closures, but I believe there are cases where closures are absolutely necessary). JavaScript开发人员学会减轻这种情况的一种方法是使用闭包(好吧,我们知道使用闭包会有性能损失,但我相信有些情况下绝对需要关闭)。

Example

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

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

    return Example;
})();

The above example respects the public/private access. 以上示例尊重公共/私人访问。

I've worked out that by using lambda syntax we can declare public closure methods within TypeScript. 我已经解决了使用lambda语法我们可以在TypeScript中声明公共闭包方法。

Example

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

It's not particularly pretty, but it works. 它不是特别漂亮,但它有效。

What I would like to know is: How would I declare private closures in TypeScript? 我想知道的是:我如何在TypeScript中声明私有闭包?

Example

class Example {

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

See more on this bugbear here: https://github.com/Microsoft/TypeScript/issues/2940 有关此bugbe的更多信息,请访问: https//github.com/Microsoft/TypeScript/issues/2940

TypeScript brings types and accessors to ES6 (and it checks both statically). TypeScript为ES6带来了类型和访问器(它会静态检查)。 The class keyword in TypeScript is the standard class keyword from ES6. class在打字稿关键字是标准class从ES6关键字。 There are no private closures in ES6 classes. ES6课程中没有私人关闭。 This syntax is not valid in ES6: 此语法是无效的ES6:

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

If you need to declare a closure that encapsulates variables, you should use the classic JavaScript way. 如果需要声明封装变量的闭包,则应使用经典的JavaScript方法。 I strongly suggest to takes advantage of the TS interfaces: 我强烈建议利用TS接口:

interface NamedObject {
    getName(): string;
}

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

let obj: NamedObject = createNamedObject();

If you really want to make class methods with closures, you can do this: 如果你真的想用闭包创建类方法,你可以这样做:

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

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

As we know, the access modifiers are only checked at compilation, thus ignored by the emitted JavaScript. 众所周知,访问修饰符仅在编译时检查,因此被发出的JavaScript忽略。

That's because privacy in this context is privacy of the API from other developer. 这是因为在这种情况下隐私是来自其他开发者的API的隐私。 If you want them to know that the method is private - provide them with a .d.ts file so their editor can know that or don't document it in the API Documentation. 如果您希望他们知道该方法是私有的 - 为他们提供.d.ts文件,以便他们的编辑可以知道或不在API文档中记录它。

In JavaScript the documentation is often regarded as the API. 在JavaScript中,文档通常被视为API。

What I would like to know is: How would I declare private closures in TypeScript? 我想知道的是:我如何在TypeScript中声明私有闭包?

You can create functions in the constructor which would declare them on the instance and not on the prototype. 您可以在构造函数中创建函数,这些函数将在实例上而不是在原型上声明它们。 This would allow you to use a closure - it also goes against prototypical inheritance and the nature of TypeScript and JavaScript. 这将允许您使用闭包 - 它也违反了原型继承以及TypeScript和JavaScript的本质。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM