वहाँ 'इस' में टाइपप्रति के लिए एक उपनाम है?

वोट
72

मैं टाइपप्रति में एक वर्ग के लिए एक विधि परिभाषित जो एक jQuery घटना के लिए एक ईवेंट हैंडलर कॉलबैक रूप में कार्य करता है कि लिखने के लिए प्रयास किया है।

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 ईवेंट हैंडलर के भीतर, टाइपप्रति 'इस' वर्ग की 'इस' होने के रूप में देखता है। हालांकि, jQuery इस संदर्भ ओवरराइड करता है और घटना के साथ जुड़े डोम वस्तु के लिए यह तय करता है।

एक वैकल्पिक ईवेंट हैंडलर के रूप में निर्माता के भीतर एक लैम्ब्डा, जिसमें मामले टाइपप्रति एक छिपे हुए केवल इस उर्फ ​​साथ बंद का एक तरह बनाता है परिभाषित करने के लिए है।

class Editor {
    textarea: JQuery;

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

मेरे सवाल है, वहाँ विधि आधारित घटना टाइपप्रति का उपयोग कर, यह jQuery व्यवहार पर काबू पाने के हैंडलर के भीतर इस संदर्भ का उपयोग करने के लिए एक और तरीका है?

06/10/2012 को 04:26
का स्रोत उपयोगकर्ता
अन्य भाषाओं में...                            


12 जवाब

वोट
97

के दायरे thisसंरक्षित है जब तीर समारोह सिंटैक्स का उपयोग () => { ... }- यहाँ एक उदाहरण से लिया है जावास्क्रिप्ट प्रोग्रामर्स के लिए टाइपप्रति

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

ध्यान दें कि this.textआप देता है Text from outer functionक्योंकि तीर समारोह वाक्य रचना "शाब्दिक गुंजाइश" बरकरार रखता है।

06/10/2012 को 15:25
का स्रोत उपयोगकर्ता

वोट
21

तो जैसा कि कहा गया है एक विधि सुनिश्चित करने के लिए कोई टाइपप्रति तंत्र हमेशा ही है यह करने के लिए नहीं है thisसूचक (और यह सिर्फ एक jQuery मुद्दा नहीं है।) मतलब यह नहीं है कि वहाँ इस मुद्दे के समाधान के लिए एक यथोचित सीधा तरीका नहीं है। आपको क्या करना होगा अपने विधि है कि पुनर्स्थापित करता है के लिए एक प्रॉक्सी उत्पन्न करने के लिए है thisअपने कॉलबैक कॉल करने से पहले सूचक। फिर आप यह घटना में पार करने से पहले कि प्रॉक्सी के साथ अपने कॉलबैक रैप करने के लिए की जरूरत है। jQuery इस बुलाया के लिए एक तंत्र में बनाया गया है jQuery.proxy()। यहाँ अपने ऊपर कोड है कि विधि का उपयोग का एक उदाहरण है (जोड़ा नोटिस $.proxy()कॉल।)

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. 
    } 
} 

यही कारण है कि एक उचित समाधान है, लेकिन मैं व्यक्तिगत रूप से मिल गया है डेवलपर्स अक्सर प्रॉक्सी कॉल शामिल करने के लिए भूल जाते हैं कि तो मैं इस समस्या के लिए एक वैकल्पिक टाइपप्रति आधारित समाधान के साथ आ गए हैं। का उपयोग करना, HasCallbacksतुम सब करने की जरूरत है नीचे वर्ग अपने वर्ग निकाले जाते हैं से है HasCallbacksऔर उसके बाद किसी भी तरीकों के साथ उपसर्ग 'cb_'उनके होगा thisसूचक स्थायी रूप से बाध्य। आप बस एक अलग के साथ कि विधि कॉल नहीं कर सकते thisसूचक जो ज्यादातर मामलों में बेहतर है। या तो तंत्र इसलिए इसकी सिर्फ इनमें से जो भी आप पाते हैं का उपयोग करना आसान काम करता है।

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({});
06/10/2012 को 06:28
का स्रोत उपयोगकर्ता

वोट
20

अन्य उत्तर में से कुछ के द्वारा कवर के रूप में, एक समारोह को परिभाषित करने के लिए तीर सिंटैक्स का उपयोग संदर्भ का कारण बनता है thisहमेशा संलग्नित क्लास का उल्लेख करने के।

तो अपने सवाल का जवाब देने के लिए, यहाँ दो साधारण कामकाज से जुड़े हैं।

तीर सिंटैक्स का उपयोग विधि संदर्भ

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

विधि तीर सिंटेक्स के उपयोग को परिभाषित करें

onFocusIn = (e: JQueryEventObject) => {
    var height = this.textarea.css('height');
}
23/12/2013 को 05:27
का स्रोत उपयोगकर्ता

वोट
6

आप निर्माता अपने उदाहरण के लिए एक सदस्य समारोह बाध्य कर सकते हैं।

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
    }
}

वैकल्पिक रूप से, बस इसे बाँध जब आप हैंडलर जोड़ने।

        this.textarea.focusin(onFocusIn.bind(this));
20/05/2014 को 15:47
का स्रोत उपयोगकर्ता

वोट
3

स्टीवन Ickman के समाधान आसान है, लेकिन अधूरा है। डैनी बेकेट और सैम के जवाब छोटा और अधिक मार्गदर्शन कर रहे हैं, और एक कॉलबैक कि दोनों गतिशील और lexically scoped "इस" एक ही समय में की जरूरत होने का एक ही सामान्य स्थिति में असफल। मेरे कोड पर जाएं, तो नीचे मेरी स्पष्टीकरण टीएल है, डॉ ...

मैं संरक्षित करने के लिए "इस" पुस्तकालय कॉलबैक साथ प्रयोग के लिए गतिशील scoping, के लिए की जरूरत है और मैं की जरूरत है एक "इस" वर्ग उदाहरण के लिए शाब्दिक scoping के साथ। मैं तर्क है कि यह एक कॉलबैक जनरेटर में उदाहरण के पारित करने के लिए, प्रभावी रूप से वर्ग उदाहरण से अधिक पैरामीटर बंद दे सबसे खूबसूरत है। संकलक आपको बताता है कि आप ऐसा करने से चूक गए। मैं lexically scoped पैरामीटर "outerThis" बुला के एक सम्मेलन है, लेकिन "स्व" का उपयोग करें या एक और नाम बेहतर हो सकता है।

"इस" कीवर्ड के उपयोग OO दुनिया से चोरी हो जाता है, और जब टाइपप्रति इसे अपनाया (ECMAScript से 6 चश्मा मुझे लगता है), वे एक lexically scoped अवधारणा और एक गतिशील scoped अवधारणा है, जब भी एक तरीका है एक अलग इकाई द्वारा कहा जाता है सम्मिश्रित । मैं इस पर एक छोटे से इस बात से नाराज हूँ, ताकि मैं इसके बारे में बंद lexically scoped वस्तु दृष्टान्त हाथ कर सकते हैं मैं टाइपप्रति में एक "स्व" कीवर्ड पसंद करेंगे। वैकल्पिक रूप से, जे एस जब यह आवश्यक है (और इस प्रकार एक ही बार में सभी वेब पृष्ठों को तोड़ने) एक स्पष्ट पहले की स्थिति 'फोन करने वाले "पैरामीटर की आवश्यकता के लिए नए सिरे से परिभाषित किया जा सकता है।

यहाँ मेरी समाधान (एक बड़ा वर्ग से अलग किया) है। विशेष रूप से एक हंस रास्ता पर पद्धतियों को बुलाया जाता है, और "dragmoveLambda" विशेष रूप से के शरीर लें:

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

}
21/03/2014 को 20:33
का स्रोत उपयोगकर्ता

वोट
3

इसे इस्तेमाल करे

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
    }

}
24/05/2013 को 02:47
का स्रोत उपयोगकर्ता

वोट
2

आप js eval फ़ंक्शन का उपयोग कर सकते हैं: var realThis = eval('this');

20/09/2014 को 13:13
का स्रोत उपयोगकर्ता

वोट
2

टाइपप्रति किसी भी अतिरिक्त रास्ता (परे नियमित जावास्क्रिप्ट का मतलब है) वापस 'असली' को पाने के लिए प्रदान नहीं करता है thisके अलावा अन्य संदर्भ thisजो कोई मौजूदा जे एस कोड के बाद से एक वापस compat नजरिए से स्वीकार्य है (वसा तीर लैम्ब्डा वाक्य रचना में प्रदान की remapping सुविधा एक का उपयोग कर किया जा सकता है =>अभिव्यक्ति)।

आप CodePlex साइट के लिए एक सुझाव पोस्ट कर सकता है, लेकिन एक भाषा डिजाइन के नजरिए से देखते शायद काफी नहीं है कि कर सकते हैं यहाँ हो, किसी भी समझदार कीवर्ड संकलक प्रदान कर सकता है पहले से ही मौजूदा JavaScript कोड द्वारा उपयोग में हो सकता है के बाद से।

06/10/2012 को 04:35
का स्रोत उपयोगकर्ता

वोट
1

मैं एक ऐसी ही समस्या का सामना करना पड़ा है। मुझे लगता है कि आप उपयोग कर सकते हैं .each()कई मामलों में रखने के लिए thisबाद में की घटनाओं के लिए एक अलग मूल्य के रूप में।

जावास्क्रिप्ट रास्ता:

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

टाइपप्रति रास्ता:

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

मुझे उम्मीद है इससे किसी को सहायता मिलेगी।

16/06/2014 को 09:17
का स्रोत उपयोगकर्ता

वोट
0

वहाँ सब से ऊपर जवाब तुलना में बहुत सरल समाधान है। असल में हम बजाय महत्वपूर्ण शब्द फ़ंक्शन का उपयोग करने का उपयोग करके जावास्क्रिप्ट करना प्रारंभ कर '=>' का निर्माण जो 'इस' में वर्ग 'इस' अनुवाद करेगा

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'); 
    }
}
11/05/2015 को 18:30
का स्रोत उपयोगकर्ता

वोट
0

इस ब्लॉग पोस्ट देखें http://lumpofcode.blogspot.com/2012/10/typescript-dart-google-web-toolkit-and.html , यह भीतर और टाइपप्रति वर्गों में कॉल के आयोजन के लिए तकनीक की विस्तृत चर्चा है।

06/12/2014 को 01:49
का स्रोत उपयोगकर्ता

वोट
0

आप करने के लिए अपने संदर्भ संग्रहीत कर सकती है this.. किसी अन्य वैरिएबल के selfशायद, और संदर्भ कि जिस तरह से एक्सेस करते हैं। मैं टाइपप्रति का उपयोग नहीं करते हैं, लेकिन यह एक तरीका है कि अतीत में वेनिला जावास्क्रिप्ट के साथ मेरे लिए सफल रहा है।

06/10/2012 को 04:30
का स्रोत उपयोगकर्ता

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