【问题标题】:Why can't I declare local variables and functions within a TypeScript class?为什么我不能在 TypeScript 类中声明局部变量和函数?
【发布时间】:2012-11-23 17:29:59
【问题描述】:

在 TypeScript 中,如果没有编译器将函数添加到原型中,我似乎无法在类中声明函数。例如:

class MyTypeScriptClass {
    // method, is added to prototype
    foo1(): void {
        alert('invoked foo1');
    }

    // private method also added to prototype
    private foo2(): void {
        alert('invoked foo2');
    }

    //// can I have a local function, without making it a private method?
    //function foo3() {
    //    alert('invoked foo3');
    //}
}

上面编译成这样:

var MyTypeScriptClass = (function () {
    function MyTypeScriptClass() { }
    MyTypeScriptClass.prototype.foo1 = function () {
        alert('invoked foo1');
    };
    MyTypeScriptClass.prototype.foo2 = function () {
        alert('invoked foo2');
    };
    return MyTypeScriptClass;
})();

我正在寻找的是可以编译为以下 JavaScript 的打字稿:

var fvm = new FlasherViewModel2();
    var MyTypeScriptClass = (function () {
        function MyTypeScriptClass() { }
        MyTypeScriptClass.prototype.foo1 = function () {
            alert('invoked foo1');
        };
        MyTypeScriptClass.prototype.foo2 = function () {
            alert('invoked foo2');
        };
        function foo3() {
            alert('invoked foo3');
        }
        return MyTypeScriptClass;
    })();

可以吗?

(顺便说一句,我知道 foo3 不能从外部代码调用。我实际上会从类中的另一个方法调用 foo3,例如,将函数传递给 jQuery fadeOut。)

【问题讨论】:

  • 您想要一个只有特定类的实例才能访问的私有函数?这听起来像private static,根据this answer 是不可能的。如果您希望 foo3 公开,是否只需将其设为 static 对您有用吗?
  • 是的,我正在寻找一个只有实例才能访问的私有函数。感谢您的链接和澄清。我能够通过使用指针函数 (lambda) 来实现相同的目标,因为我试图处理的问题是丢失内部作用域函数中的外部 this 引用。

标签: javascript typescript


【解决方案1】:

正如 apsillers 所说,private static 可能是您想要的。虽然当前版本不支持它,但您将来可以在 TypeScript 中拥有一个 private static 成员(设计团队根据类似的反馈改变了这个想法)。

【讨论】:

    【解决方案2】:

    我刚刚发现了另一种在 typescript 类中使用私有方法的方法,尽管这种模式可能闻起来有点滑稽。据我所知,只有将类包装在module 中时才能执行此操作。例如:

    module MyApp {
        // not accessible externally, `this` must be passed in if needed
        function foo3(that: MyTypeScriptClass): void {
            that.foo1();
            alert('invoked foo3');
        }
    
        // not accessible externally
        function foo4(): void {
            alert('invoked foo4');
        }
    
        export class MyTypeScriptClass {
            // normal method, is added to prototype
            foo1(): void {
                alert('invoked foo1');
            }
    
            // private method also added to prototype, is accessible externally
            private foo2(): void {
                alert('invoked foo2');
                foo3(this);
                foo4();
            }
        }
    }
    

    上面编译成:

    var MyApp;
    (function (MyApp) {
        function foo3(that) {
            that.foo1();
            alert('invoked foo3');
        }
        function foo4() {
            alert('invoked foo4');
        }
        var MyTypeScriptClass = (function () {
            function MyTypeScriptClass() { }
            MyTypeScriptClass.prototype.foo1 = function () {
                alert('invoked foo1');
            };
            MyTypeScriptClass.prototype.foo2 = function () {
                alert('invoked foo2');
                foo3(this);
                foo4();
            };
            return MyTypeScriptClass;
        })();
        MyApp.MyTypeScriptClass = MyTypeScriptClass;    
    })(MyApp || (MyApp = {}));
    

    通过上述方法,外部 javascript 可以在 MyTypeScriptClass 的实例上调用 foo2(),但在运行时外部无法访问 foo3()foo4()。最大的警告是,如果您的私有方法需要访问实例的成员,您必须将this 作为函数参数传入。本质上,这些是私有静态方法。

    var instance = new MyApp.MyTypeScriptClass();
    
    // public, accessible externally
    instance.foo1();
    
    // will not compile in a .ts file, but works at runtime from manual js file
    instance.foo2();
    
    // runtime exception, foo3 is not defined
    foo3(instance);
    MyApp.foo3(instance);
    
    // runtime exception, foo4 is not defined
    foo4();
    MyApp.foo4();
    

    这种方法也适用于标量变量,但变量本质上也是静态的——对于不同的类实例,你不能有不同的值。为此,据我所知,您仍然需要在类中声明它们。将它们标记为 private 将阻止 typescript 编译器允许外部调用它们,但其他 javascript 代码仍然可以从外部访问它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-11
      • 2019-02-08
      • 1970-01-01
      • 2020-05-31
      • 1970-01-01
      • 2014-04-13
      • 2019-06-12
      • 1970-01-01
      相关资源
      最近更新 更多