'Bu' in typescript için bir takma var mı?

oy
72

Bir jQuery olay bir olay işleyicisi geri arama gibi davranan tanımlanmış bir yöntemi vardır daktilo bir sınıf yazmak için teşebbüs ettik.

class Editor {
    textarea: JQuery;

    constructor(public id: string) {
        this.textarea = $(id);
        this.textarea.focusin(onFocusIn);
    }

    onFocusIn(e: JQueryEventObject) {
        var height = this.textarea.css('height'); // <-- This is not good.
    }
}

onFocusIn olay işleyicisi içinde, typescript 'bu' sınıfının 'bu' olarak görüyor. Ancak, jQuery bu referansına göre önceliklidir ve etkinlikle ilişkili DOM nesnesine ayarlar.

Bir alternatif vaka typescript gizli _this takma adı ile kapatılması bir tür yaratan olay işleyici olarak yapıcı içerisinde bir lambda, tanımlamaktır.

class Editor {
    textarea: JQuery;

    constructor(public id: string) {
        this.textarea = $(id);
        this.textarea.focusin((e) => {
            var height = this.textarea.css('height'); // <-- This is good.
        });
    }
}

Benim sorum bu jQuery davranışı aşmak için, typescript kullanarak yöntem tabanlı olay işleyicisi içinde bu başvuruya erişmek için başka bir yol yoktur, değil mi?

Oluştur 06/10/2012 saat 04:26
kaynak kullanıcı
Diğer dillerde...                            


12 cevaplar

oy
97

Kapsamı thisok fonksiyonu sözdizimi kullanırken korunur () => { ... }- buradan alınan bir örnek JavaScript programcılar için typescript .

var ScopeExample = { 
  text: "Text from outer function", 
  run: function() { 
    setTimeout( () => { 
      alert(this.text); 
    }, 1000); 
  } 
};

Not this.textverir Text from outer functionok fonksiyonu sözdizimi "sözcük kapsamını" korur çünkü.

Cevap 06/10/2012 saat 15:25
kaynak kullanıcı

oy
21

Belirtildiği gibi Yani öyle her zaman bağlı bir yöntem sağlamaya yönelik hiçbir typescript mekanizma yoktur thisbu sorunu gidermek için bir makul basit yolu yoktur anlamına gelmez işaretçi (ve bu sadece bir jQuery sorun değildir.). Ne gerek geri yükler senin yöntem için bir proxy oluşturmak için thissizin geri arama çağırmadan önce işaretçi. Daha sonra olay haline geçirmeden önce o proxy ile geri arama sarmak gerekiyor. jQuery denilen Bunun için bir yerleşik bir mekanizmaya sahiptir jQuery.proxy(). İşte bu yöntemi kullanarak yukarıdaki kod örneği (ilave fark $.proxy()çağrı.)

class Editor { 
    textarea: JQuery; 

    constructor(public id: string) { 
        this.textarea = $(id); 
        this.textarea.focusin($.proxy(onFocusIn, this)); 
    } 

    onFocusIn(e: JQueryEventObject) { 
        var height = this.textarea.css('height'); // <-- This is not good. 
    } 
} 

Bu makul bir çözüm ama şahsen ben bu soruna alternatif bir typescript tabanlı bir çözüm ile geldim bu yüzden geliştiriciler genellikle vekil çağrıyı eklemeyi unutmayın saptadık. Kullanarak, HasCallbacksyapmanız gereken tüm aşağıda sınıfı adresinin sınıf türetmek olduğu HasCallbacksöneki her yöntem ve sonra 'cb_'onların olacak thisişaretçi kalıcı bağlı. Sadece farklı bir ile bu yöntemi arayamazsınız thisçoğu durumda tercih edilir pointer. Ya mekanizma böylece kullanımı daha kolay bulmak hangisi onun sadece çalışır.

class HasCallbacks {
    constructor() {
        var _this = this, _constructor = (<any>this).constructor;
        if (!_constructor.__cb__) {
            _constructor.__cb__ = {};
            for (var m in this) {
                var fn = this[m];
                if (typeof fn === 'function' && m.indexOf('cb_') == 0) {
                    _constructor.__cb__[m] = fn;                    
                }
            }
        }
        for (var m in _constructor.__cb__) {
            (function (m, fn) {
                _this[m] = function () {
                    return fn.apply(_this, Array.prototype.slice.call(arguments));                      
                };
            })(m, _constructor.__cb__[m]);
        }
    }
}

class Foo extends HasCallbacks  {
    private label = 'test';

    constructor() {
        super();

    }

    public cb_Bar() {
        alert(this.label);
    }
}

var x = new Foo();
x.cb_Bar.call({});
Cevap 06/10/2012 saat 06:28
kaynak kullanıcı

oy
20

İşlev tanımlamak için ok sözdizimi kullanarak, diğer bazı yanıtlar kapsadığı gibi başvurular neden thishep kapsayan sınıfına başvurmak için.

Yani soruyu cevaplamak için, burada iki basit geçici çözümler vardır.

Ok sözdizimi kullanılarak yöntemi Referans

constructor(public id: string) {
    this.textarea = $(id);
    this.textarea.focusin(e => this.onFocusIn(e));
}

ok sözdizimi kullanarak yöntemi tanımlayın

onFocusIn = (e: JQueryEventObject) => {
    var height = this.textarea.css('height');
}
Cevap 23/12/2013 saat 05:27
kaynak kullanıcı

oy
6

Sen yapıcısı onun örneğine üye işlev bağlayabilir.

class Editor {
    textarea: JQuery;

    constructor(public id: string) {
        this.textarea = $(id);
        this.textarea.focusin(onFocusIn);
        this.onFocusIn = this.onFocusIn.bind(this); // <-- Bind to 'this' forever
    }

    onFocusIn(e: JQueryEventObject) {
        var height = this.textarea.css('height');   // <-- This is now fine
    }
}

Eğer işleyici eklerken Alternatif sadece bağlamak.

        this.textarea.focusin(onFocusIn.bind(this));
Cevap 20/05/2014 saat 15:47
kaynak kullanıcı

oy
3

Steven Ickman çözümü kullanışlı ama eksik. Danny Becket ve Sam'in cevapları daha kısa ve daha manuel, ve dinamik ve lexically kapsamlı hem "bu" aynı zamana ihtiyacı bir geri arama sahip aynı genel durumda başarısız. Aşağıda benim açıklama TL ise benim kod atlama; DR ...

Ben "bu" dinamik kütüphane geri aramaları ile kullanılmak üzere kapsama alınması için korumak gerekir ve ben olması gereken bir "bu" sınıf örneğine sözcük kapsama alınması ile. Ben etkili sınıf örneği üzerinden parametre kapatılması icar, bir geri arama jeneratörüne örneğini geçmek en zarif olduğunu savunuyorlar. Bunu yaparken cevapsız eğer derleyici söyler. Ben lexically kapsamlı parametresi "outerThis" çağıran kuralı, ancak "kendini" kullanabilir veya başka bir isim daha iyi olabilir.

"Bu" anahtar kelime kullanımı OO dünyasından çalınmış ve typescript (sanırım ECMAScript'e 6 spesifikasyonları) o zaman kabul, onlar bir yöntemdir farklı bir varlık tarafından arandığı her bir lexically kapsamlı kavram ve dinamik kapsamlı kavram, conflated edilir . Bu işte biraz kızgın değilim; Bunu ortadan lexically kapsamlı nesne örneğini el böylece ben daktilo bir "öz" anahtar kelimesini tercih ediyorum. Alternatif olarak, JS gerekli (ve böylece bir çırpıda tüm web sayfaları kırmak) olduğunda açık bir birinci pozisyon "arayan" parametresini gerektirecek şekilde yeniden tanımlandı olabilir.

İşte (büyük bir sınıftan çıkartıldı) benim çözüm. yöntemler denir gidiş yönünden özellikle bir kaz ve özellikle de "dragmoveLambda" gövdesini atın:

export class OntologyMappingOverview {

initGraph(){
...
// Using D3, have to provide a container of mouse-drag behavior functions
// to a force layout graph
this.nodeDragBehavior = d3.behavior.drag()
        .on("dragstart", this.dragstartLambda(this))
        .on("drag", this.dragmoveLambda(this))
        .on("dragend", this.dragendLambda(this));

...
}

dragmoveLambda(outerThis: OntologyMappingOverview): {(d: any, i: number): void} {
    console.log("redefine this for dragmove");

    return function(d, i){
        console.log("dragmove");
        d.px += d3.event.dx;
        d.py += d3.event.dy;
        d.x += d3.event.dx;
        d.y += d3.event.dy; 

        // Referring to "this" in dynamic scoping context
        d3.select(this).attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

        outerThis.vis.selectAll("line")
            .filter(function(e, i){ return e.source == d || e.target == d; })
            .attr("x1", function(e) { return e.source.x; })
            .attr("y1", function(e) { return e.source.y; })
            .attr("x2", function(e) { return e.target.x; })
            .attr("y2", function(e) { return e.target.y; });

    }
}

dragging: boolean  =false;
// *Call* these callback Lambda methods rather than passing directly to the callback caller.
 dragstartLambda(outerThis: OntologyMappingOverview): {(d: any, i: number): void} {
        console.log("redefine this for dragstart");

        return function(d, i) {
            console.log("dragstart");
            outerThis.dragging = true;

            outerThis.forceLayout.stop();
        }
    }

dragendLambda(outerThis: OntologyMappingOverview): {(d: any, i: number): void}  {
        console.log("redefine this for dragend");

        return function(d, i) {
            console.log("dragend");
            outerThis.dragging = false;
            d.fixed = true;
        }
    }

}
Cevap 21/03/2014 saat 20:33
kaynak kullanıcı

oy
3

Bunu dene

class Editor 
{

    textarea: JQuery;
    constructor(public id: string) {
        this.textarea = $(id);
        this.textarea.focusin((e)=> { this.onFocusIn(e); });
    }

    onFocusIn(e: JQueryEventObject) {
        var height = this.textarea.css('height'); // <-- This will work
    }

}
Cevap 24/05/2013 saat 02:47
kaynak kullanıcı

oy
2

Sen js eval işlevini kullanabilirsiniz: var realThis = eval('this');

Cevap 20/09/2014 saat 13:13
kaynak kullanıcı

oy
2

Typescript geri 'gerçek' almak için herhangi bir ekstra yol (düzenli JavaScript demektir ötesinde) sağlamaz thisdışında referans thishiçbir mevcut JS kodu beri arka compat perspektiften izin verilen olan (yağ ok lambda sözdiziminde sağlanan remapping kolaylık bir kullanıyor olabilir =>) ifade.

Sen codeplex sitesine bir öneri göndermek, ancak bir dil tasarım açısından bu kadar muhtemelen orada değil olabilir olabilir derleyici zaten var olan JavaScript kodu tarafından kullanılıyor olabilir sağlayabilir herhangi aklı başında, anahtar kelime, burada ne.

Cevap 06/10/2012 saat 04:35
kaynak kullanıcı

oy
1

Ben benzer bir sorun ile karşı karşıya kaldılar. Kullanabileceğin düşünüyorum .each()tutmak için birçok durumda thisdaha sonraki olaylar için farklı bir değer olarak.

JavaScript yol:

$(':input').on('focus', function() {
  $(this).css('background-color', 'green');
}).on('blur', function() {
  $(this).css('background-color', 'transparent');
});

Typescript yol:

$(':input').each((i, input) => {
  var $input = $(input);
  $input.on('focus', () => {
    $input.css('background-color', 'green');
  }).on('blur', () => {
    $input.css('background-color', 'transparent');
  });
});

Bu kimse yardımcı olur.

Cevap 16/06/2014 saat 09:17
kaynak kullanıcı

oy
0

her şeyden cevaplar çok daha basit bir çözüm yoktur. Temelde biz anahtar kelime işlevini kullanarak yerine kullanarak JavaScript geri düşmek '=>' 'Bu' halinde sınıfı 'bu' tercüme hangi inşa

class Editor {
    textarea: JQuery;

    constructor(public id: string) {
        var self = this;                      // <-- This is save the reference
        this.textarea = $(id);
        this.textarea.focusin(function() {   // <-- using  javascript function semantics here
             self.onFocusIn(this);          //  <-- 'this' is as same as in javascript
        });
    }

    onFocusIn(jqueryObject : JQuery) {
        var height = jqueryObject.css('height'); 
    }
}
Cevap 11/05/2015 saat 18:30
kaynak kullanıcı

oy
0

Bu blog yazısı kontrol edin http://lumpofcode.blogspot.com/2012/10/typescript-dart-google-web-toolkit-and.html içinde ve typescript sınıfları arasında aramaları düzenlemek için tekniklerin ayrıntılı bir tartışma vardır.

Cevap 06/12/2014 saat 01:49
kaynak kullanıcı

oy
0

Bu hizmeti kullanmak için başvuru depolayabilir this.. başka bir değişkende selfbelki ve bu şekilde başvuru erişin. Ben typescript kullanmayın, ama bu geçmişte vanilya javascript ile benim için başarılı olmuştur bir yöntem.

Cevap 06/10/2012 saat 04:30
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more