javascript - Neden bir TypeScript sınıfı içinde yerel değişkenler ve fonksiyonlar bildiremiyorum?


TypeScript'te, bir sınıfta bir fonksiyonu bildirmeye çalıştığımda, derleyicinin bunu prototype'a eklemeden kalmasını sağlayamıyorum. Örneğin:

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');
    //}
}

Yukarıdakiler buna derlenir:

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

Aradığım şey, aşağıdaki JavaScript'e derlenebilen TypeScript'tir:

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;
    })();

Yapılabilir mi?

(Bir not olarak, foo3'ün dış koddan çağrılabilir olmayacağını biliyorum. Aslında foo3'ü sınıfın içindeki başka bir yöntemden çağıracağım, örneğin bir fonksiyonu jQuery fadeOut'a geçirmek için.)

Cevap #1

As apsillers'ın belirttiği gibi, private static muhtemelen istediğiniz şeydir. Mevcut sürümlerde desteklenmese de, gelecekte bir noktada TypeScript'te bir private static üyeye sahip olabileceksiniz (tasarım ekibi, buna benzer geri bildirimler temelinde fikrini değiştirdi).

Cevap #2

Typescript sınıfında özel yöntemlere sahip olmanın başka bir yolunu yeni keşfettim, ancak bu yöntem biraz garip görünebilir. Anladığım kadarıyla, bunu ancak sınıfı bir module içine sardığınızda yapabilirsiniz. Örneğin:

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();
        }
    }
}

Yukarıdaki şunları derler:

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 = {}));

Yukarıdakilerle, harici javascript, bir MyTypeScriptClass örneğinde foo2() çağırabilir, ancak foo3() ve foo4() çalışma zamanında harici olarak erişilebilir değildir. En büyük uyarı, eğer özel metodunuzun örneğin üyelerine erişmesi gerekiyorsa, this'i bir fonksiyon parametresi olarak geçirmeniz gerektiğidir. Temelde bunlar özel statik metodlardır.

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();

Bu yaklaşım temel değişkenler (scalar variables) ile de bir şekilde çalışıyor, ancak değişkenler de aslında statik -- farklı sınıf örnekleri için farklı değerlere sahip olamazsınız. Görünüşe göre bunu yapmak için, onları yine sınıf içinde tanımlamanız gerekiyor. private olarak işaretlemek, TypeScript derleyicisinin dışarıdan yapılan çağrılara izin vermesini engeller, ancak diğer JavaScript kodları yine de onlara dışarıdan erişebilir.

İlgili makaleler