जावास्क्रिप्ट में अनाम कार्यों पर removeEventListener


103

मेरे पास एक ऐसी वस्तु है जिसमें इसके तरीके हैं। इन विधियों को एक अनाम फ़ंक्शन के अंदर ऑब्जेक्ट में डाला जाता है। यह इस तरह दिख रहा है:

var t = {};
window.document.addEventListener("keydown", function(e) {
    t.scroll = function(x, y) {
        window.scrollBy(x, y);
    };
    t.scrollTo = function(x, y) {
        window.scrollTo(x, y);
    };
});  

(बहुत अधिक कोड है, लेकिन यह समस्या दिखाने के लिए पर्याप्त है)

अब मैं कुछ मामलों में इवेंट श्रोता को रोकना चाहता हूं। इसलिए मैं एक हटाने का काम करने की कोशिश कर रहा हूँ लेकिन मैं यह कैसे करना है यह पता नहीं लगा सकता। मैंने अन्य सवालों में पढ़ा है कि यह हटाने योग्य नहीं है कि गुमनाम कार्यों पर हटानेवाला काम करता है, लेकिन क्या इस स्थिति में भी ऐसा है?

अनाम कार्य के अंदर t में एक विधि है और इसलिए मुझे लगा कि यह संभव है। इस तरह दिखता है:

t.disable = function() {
    window.document.removeEventListener("keydown", this, false);
}

मैं ऐसा क्यों नहीं कर सकता?

क्या ऐसा करने का कोई और (अच्छा) तरीका है?

बोनस की जानकारी; यह केवल सफारी में काम करना है, इसलिए लापता IE का समर्थन करता है।


यह फ़ंक्शन क्यों नहीं सहेजता है? ईवेंट हैंडलर एक अनाम फ़ंक्शन नहीं हो सकता है।
21

2
मुझे पता है कि यह थोड़ी देर है, लेकिन आप किसी तत्व के बारे में डेटा संग्रहीत करने के लिए Node.setUserData /Node.getUserData विधियों का उपयोग भी कर सकते हैं । उदाहरण के लिए, जब आपको एनॉन श्रोता को सेट करने की आवश्यकता होती है (और इसे हटाने में सक्षम), पहले उपयोगकर्ता फ़ंक्शन (Elem.setUserData('eventListener', function(e){console.log('Event fired.');}, null);को एनॉन फ़ंक्शन पर सेट करें और फिर Elem.addEventListener ('इवेंट', Elem.getUserUserLata ('eventListener'), गलत) करें; ... और निष्कासन के लिए समान। आशा है कि आप यह ठीक देख सकते हैं।
चेस

संपादित करें: पिछली टिप्पणी के अनुसार, मेरा अनुमान है कि केवल फ़ायरफ़ॉक्स में काम करता है ... मैंने अभी IE8 (IE9 अज्ञात), सफारी 5.1.2, क्रोम (), ओपेरा 11..नहीं पासा
पीछा

जवाबों:


78

मेरा मानना ​​है कि यह एक अनाम फ़ंक्शन का बिंदु है, इसमें एक नाम या इसे संदर्भित करने का एक तरीका नहीं है।

यदि मैं आप होता तो मैं केवल एक नामांकित फ़ंक्शन बनाता, या इसे एक चर में डाल देता ताकि आपके पास इसका संदर्भ हो।

var t = {};
var handler = function(e) {
    t.scroll = function(x, y) {
        window.scrollBy(x, y);
    };
    t.scrollTo = function(x, y) {
        window.scrollTo(x, y);
    };
};
window.document.addEventListener("keydown", handler);

फिर आप इसे हटा सकते हैं

window.document.removeEventListener("keydown", handler);   

3
आपके जवाब के लिए धन्यवाद। मैं साथ गया: var हैंडलर; window.document.addEventListener ( "keydown", हैंडलर = समारोह (ई) {लेकिन क्यों "इस" घटना श्रोता को संदर्भित नहीं करती कि मैं क्या समझ में नहीं आता है घटना श्रोता एक वस्तु नहीं होना चाहिए।?
bitkid

1
thisकीवर्ड भ्रमित किया जा सकता है। इस पर पढ़ने के लिए एक अच्छी जगह है quirksmode.org/js/this.html
एडम हीथ

आपका बहुत बहुत धन्यवाद। यह सबसे ज्यादा मददगार था।
बिटक्वाइन

मैं एक वेबसाइट पर वास्तव में लगातार विज्ञापन को अवरुद्ध करने के लिए ऐसा करने की कोशिश कर रहा हूं। मुझे पता है कि यह अनाम कार्यों का बिंदु है, लेकिन इसका मतलब यह नहीं है कि मैं यह नहीं जानना चाहूंगा कि यह कैसे करना है।
व्याट8740

@bitkid: एक हैंडलर फ़ंक्शन के अंदर (यह एक तीर फ़ंक्शन नहीं है) यह मानते हुए, thisउस तत्व को संदर्भित करता है जिसे श्रोता जोड़ा जाता है, न कि स्वयं इवेंट (जो पैरामीटर होगा e)। इसलिए this === e.currentTarget। पढ़ने developer.mozilla.org/en-US/docs/Web/API/EventTarget/...
chharvey

100

यदि आप वास्तविक फ़ंक्शन के अंदर हैं, तो आप फ़ंक्शन के संदर्भ के रूप में तर्कों का उपयोग कर सकते हैं। जैसे की:

button.addEventListener('click', function() {
      ///this will execute only once
      alert('only once!');
      this.removeEventListener('click', arguments.callee);
});

EDIT: यदि आप सख्त मोड में काम कर रहे हैं तो यह काम नहीं करेगा ( "use strict";)


2
यह अच्छा है क्योंकि यह गुमनाम कार्यों (नाम स्थान आदि को प्रदूषित नहीं करता) के फायदों को बरकरार रखता है।
bompf

3
WinJS ऐप में इसे आज़माया गया, अगली त्रुटि मिली: "तर्क की वस्तु की 'कैली' संपत्ति तक पहुँचना सख्त मोड में अनुमति नहीं है"
वैलेंटाइन कैंटर

1
@ValentinKantor: क्योंकि कोड में कुछ "सख्त उपयोग" है; कथन, और आप कड़ाई में कैली का उपयोग नहीं कर सकते।
ओएमए

19
इनलाइन फ़ंक्शन को एक नाम दें और आप तर्कों का सहारा लिए बिना इसे संदर्भित कर सकते हैं। संदर्भ:button.addEventListener('click', function handler() { this.removeEventListener('click', handler); });
हैरी लव

4
जैसा कि मोज़िला में कहा गया है: "चेतावनी: ECMAScript (ES5) के 5 वें संस्करण में तर्कों का उपयोग वर्जित है। सख्त (सख्त) मोड में। तर्कों का उपयोग करने से बचें। खुद फोन करना चाहिए। "
दोस्त

50

ओटो नेस्करेला के समाधान का एक संस्करण जो सख्त मोड में काम करता है:

button.addEventListener('click', function handler() {
      ///this will execute only once
      alert('only once!');
      this.removeEventListener('click', handler);
});

4
सुंदर समाधान!
एरिक नोरक्रॉस

2
यह सही तरीका नहीं हो सकता है लेकिन यह सबसे आसान काम है।
विग्नेश

7
window.document.removeEventListener("keydown", getEventListeners(window.document.keydown[0].listener));  

कई अनाम कार्य हो सकते हैं, कीडाउन 1

चेतावनी: केवल काम करता है Chrome Dev Toolsऔर कोड में उपयोग नहीं किया जा सकता : लिंक


2
धन्यवाद, आपने एक पहेली को हल किया है, कम से कम क्रोम में, जोकर ने जो कहा, वह असंभव था। यार, यू आर लाइक ... बैटमैन!
जेसनएक्सए

20
getEventListenersलगता है कि क्रोम देव-टूल्स का हिस्सा है, इसलिए डिबगिंग के अलावा किसी भी चीज़ के लिए वास्तव में प्रयोग करने योग्य नहीं है।
DBS

1
बस इसकी कोशिश की, पुष्टि की कि यह केवल Devtools में उपलब्ध है और जब एक पृष्ठ के अंदर एक स्क्रिप्ट में शामिल नहीं है।
एंड्रेस रिओप्रियो

5

आधुनिक ब्राउज़रों में आप निम्न कार्य कर सकते हैं ...

button.addEventListener( 'click', () => {
    alert( 'only once!' );
}, { once: true } );

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters


कूल जब तक आपको पता नहीं चलता कि IE का कोई संस्करण और न ही किनारे <16 वास्तव में इस सुविधा का समर्थन करते हैं। कम से कम 5 वर्षों में हम इसका उपयोग कर सकते हैं, तब से IE होगा (पढ़ा जाना चाहिए: पदावनत होना चाहिए), एज ने अपनी जगह ले ली होगी और यह अपनी "EdgeHTML" चीज़ के बजाय वेबकिट इंजन का उपयोग करेगा।
सिडऑफ

1
DOM लेवल 4 प्रविष्टियों के लिए इस पॉलीफ़िल के साथ
shunryu111

2

इतना गुमनाम विकल्प नहीं

element.funky = function() {
    console.log("Click!");
};
element.funky.type = "click";
element.funky.capt = false;
element.addEventListener(element.funky.type, element.funky, element.funky.capt);
// blah blah blah
element.removeEventListener(element.funky.type, element.funky, element.funky.capt);

एंडी से प्रतिक्रिया प्राप्त करने के बाद से ( काफी सही है, लेकिन कई उदाहरणों के साथ, मैं इस विचार का एक प्रासंगिक विस्तार दिखाना चाहता हूं ), यहां एक कम जटिल प्रदर्शनी है:

<script id="konami" type="text/javascript" async>
    var konami = {
        ptrn: "38,38,40,40,37,39,37,39,66,65",
        kl: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
    };
    document.body.addEventListener( "keyup", function knm ( evt ) {
        konami.kl = konami.kl.slice( -9 );
        konami.kl.push( evt.keyCode );
        if ( konami.ptrn === konami.kl.join() ) {
            evt.target.removeEventListener( "keyup", knm, false );

            /* Although at this point we wish to remove a listener
               we could easily have had multiple "keyup" listeners
               each triggering different functions, so we MUST
               say which function we no longer wish to trigger
               rather than which listener we wish to remove.

               Normal scoping will apply to where we can mention this function
               and thus, where we can remove the listener set to trigger it. */

            document.body.classList.add( "konami" );
        }
    }, false );
    document.body.removeChild( document.getElementById( "konami" ) );
</script>

यह एक प्रभावी रूप से अनाम फ़ंक्शन संरचना की अनुमति देता है, व्यावहारिक रूप से हटाए गए कैली के उपयोग से बचा जाता है , और आसान हटाने की अनुमति देता है।

संयोग से : श्रोता को सेट करने के तुरंत बाद स्क्रिप्ट तत्व को हटाना कोड को छिपाने के लिए एक प्यारा टोटका है जो पसंद करेगा आँखों को चुभने के लिए स्पष्ट रूप से स्पष्ट नहीं था ( आश्चर्य को खराब करेगा; ;-)

तो विधि ( और अधिक सरल ) है:

element.addEventListener( action, function name () {
    doSomething();
    element.removeEventListener( action, name, capture );
}, capture );

2
यह जटिल है।
बेन सिंक्लेयर

@ और मैं सहमत हूँ, की तरह, लेकिन यह दिखाने की कोशिश कर रहा था कि एक गुमनाम फ़ंक्शन को हटाने का कोई तरीका नहीं है। इसे किसी तरह से संदर्भित किया जाना चाहिए (यहां तक ​​कि कैली (बुरा है, एम'के) फ़ंक्शन को संदर्भित कर रहा है), और इस प्रकार फ़ंक्शन को संदर्भित किया जा सकता है, बस एक (अन्य) तरीके का एक उदाहरण प्रदान किया गया है - यह कैसे भागों से बना है समान रूप से बाद के संदर्भ (महत्वपूर्ण भाग) के लिए संग्रहीत किया जा सकता है। जाहिर है कि वास्तव में गुमनाम फंक्शन कुछ हद तक ऑन-द-फ्लाई बनाया जाता है, और इसलिए बाद में पता चलता है कि कौन सा इवेंट एक्शन / टाइप है और क्या कैप्चर का उपयोग किया गया है, यह भी पता होना चाहिए। वैसे भी, यहाँ एक बेहतर तरीका है :-)
फ्रेड गंड

मेरे लिए पूरी तरह से काम किया। मैं फ़ंक्शन में तर्क पास करने का दूसरा तरीका नहीं देख सकता था, क्योंकि यह गुमनाम नहीं हो सकता था।
निकोडेमस 13

2

यह आदर्श नहीं है क्योंकि यह सभी को हटा देता है, लेकिन आपकी आवश्यकताओं के लिए काम कर सकता है:

z = document.querySelector('video');
z.parentNode.replaceChild(z.cloneNode(1), z);

एक नोड क्लोनिंग इसके सभी विशेषताओं और उनके मूल्यों को कॉपी करता है, जिसमें आंतरिक (-लाइन) श्रोता शामिल हैं। यह addEventListener () का उपयोग करते हुए इवेंट श्रोताओं को कॉपी नहीं करता है

Node.cloneNode ()


यह बिल्कुल शानदार है
अहमद अल्फी

1

जावास्क्रिप्ट : addEventListener विधि निर्दिष्ट श्रोता को EventTarget (तत्व | दस्तावेज़ | विंडो) पर पंजीकृत करती है, जिसे यह कहा जाता है।

EventTarget। addEventListener ( event_type , handler_function, Bubbling | कैप्चरिंग );

माउस, कीबोर्ड ईवेंट्स उदाहरण वेबकॉन कंसोल में परीक्षण:

var keyboard = function(e) {
    console.log('Key_Down Code : ' + e.keyCode);
};
var mouseSimple = function(e) {
    var element = e.srcElement || e.target;
    var tagName = element.tagName || element.relatedTarget;
    console.log('Mouse Over TagName : ' + tagName);    
};
var  mouseComplex = function(e) {
    console.log('Mouse Click Code : ' + e.button);
} 

window.document.addEventListener('keydown',   keyboard,      false);
window.document.addEventListener('mouseover', mouseSimple,   false);
window.document.addEventListener('click',     mouseComplex,  false);

removeEventListener विधि पहले से EventTarget.addEventListener () के साथ पंजीकृत ईवेंट श्रोता को हटा देती है।

window.document.removeEventListener('keydown',   keyboard,     false);
window.document.removeEventListener('mouseover', mouseSimple,  false);
window.document.removeEventListener('click',     mouseComplex, false);

क्या में उपयोग कर सकता हूँ


1

इसे और अधिक अप-टू-डेट दृष्टिकोण देने के लिए:

//one-time fire
element.addEventListener('mousedown', {
  handleEvent: function (evt) {
    element.removeEventListener(evt.type, this, false);
  }
}, false);

2
एक स्पष्टीकरण अच्छा होगा।
पौल बक

1

मैं एक ही समस्या में फंस गया हूं और यह सबसे अच्छा समाधान था जो मुझे मिल सकता है:

/*Adding the event listener (the 'mousemove' event, in this specific case)*/
element.onmousemove = function(event) {
    /*do your stuff*/
};
/*Removing the event listener*/
element.onmousemove = null;

कृपया ध्यान रखें कि मैंने केवल windowतत्व के लिए और 'mousemove'घटना के लिए यह परीक्षण किया है , इसलिए इस दृष्टिकोण के साथ कुछ समस्याएं हो सकती हैं।


0

संभवतः जो आप पूछ रहे हैं उसके संदर्भ में सबसे अच्छा समाधान नहीं है। मैंने अभी भी घटना श्रोता मंगलाचरण के साथ अनाम फ़ंक्शन घोषित इनलाइन को हटाने के लिए एक कुशल विधि निर्धारित नहीं की है।

मैं व्यक्तिगत रूप <target>से इवेंट श्रोता मंगलाचरण के बाहर फ़ंक्शन को स्टोर करने और घोषित करने के लिए एक चर का उपयोग करता हूं जैसे:

const target = document.querySelector('<identifier>');

function myFunc(event) { function code; }

target.addEventListener('click', myFunc);

फिर श्रोता को हटाने के लिए:

target.removeEventListener('click', myFunc);

शीर्ष अनुशंसा आपको नहीं मिलेगी लेकिन अनाम फ़ंक्शंस को निकालने के लिए एकमात्र समाधान जो मैंने उपयोगी पाया है वह है एचटीएमएल तत्व को हटाने के लिए। मुझे यकीन है कि एक बेहतर वैनिला जेएस विधि होनी चाहिए, लेकिन मैंने अभी तक इसे नहीं देखा है।


0

मुझे पता है कि यह काफी पुराना धागा है, लेकिन मुझे लगा कि मैं इसे उपयोगी मानने वालों के लिए अपने दो सेंट में रख सकता हूं।

स्क्रिप्ट (अप्रसिद्ध विधि नामों के बारे में माफी):

window.Listener = {
    _Active: [],
    remove: function(attached, on, callback, capture){
        for(var i = 0; i < this._Active.length; i++){
            var current = this._Active[i];
            if(current[0] === attached && current[1] === on && current[2] === callback){
                attached.removeEventListener(on, callback, (capture || false));
                return this._Active.splice(i, 1);
            }
        }
    }, removeAtIndex(i){
        if(this._Active[i]){
            var remove = this._Active[i];
            var attached = remove[0], on = remove[1], callback = remove[2];
            attached.removeEventListener(on, callback, false);
            return this._Active.splice(i, 1);
        }
    }, purge: function(){
        for(var i = 0; i < this._Active.length; i++){
            var current = this._Active[i];
            current[0].removeEventListener(current[1], current[2]);
            this._Active.splice(i, 1);
        }
    }, declare: function(attached, on, callback, capture){
        attached.addEventListener(on, callback, (capture || false));
        if(this._Active.push([attached, on, callback])){
            return this._Active.length - 1;
        }
    }
};

और आप इसे इस तरह से उपयोग कर सकते हैं:

// declare a new onclick listener attached to the document
var clickListener = Listener.declare(document, "click" function(e){
    // on click, remove the listener and log the clicked element
    console.log(e.target);
    Listener.removeAtIndex(clickListener);
});

// completely remove all active listeners 
// (at least, ones declared via the Listener object)
Listener.purge();

// works exactly like removeEventListener
Listener.remove(element, on, callback);

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.