प्रोग्राम में एक जावास्क्रिप्ट फ़ंक्शन में कोड जोड़ना


114

मैं मूल JS कोड को संशोधित किए बिना एक मौजूदा JS लाइब्रेरी को कस्टमाइज़ करने का प्रयास कर रहा हूं। यह कोड कुछ बाहरी जेएस फाइलों में लोड होता है, जिनकी मेरे पास पहुंच होती है, और मैं जो करना चाहता हूं, वह मूल फाइल में निहित कार्यों में से एक को बदलकर पूरी चीज को दूसरी जेएस फाइल में पेस्ट और पेस्ट किए बिना किया जाता है।
इसलिए, उदाहरण के लिए, जेएस की सीमाएँ इस तरह एक कार्य हो सकती हैं:

var someFunction = function(){
    alert("done");
}

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

मुझे पूरा यकीन नहीं है कि यह संभव है, लेकिन मुझे लगा कि मैं जाँच करूँगा।


3
के पहले सवाल का जवाब इस आप मदद करनी चाहिए
DarkAjax

क्या आप कॉलबैक फ़ंक्शन की तरह कुछ चाहते हैं?
sinemetu1

जवाबों:


220

यदि someFunctionविश्व स्तर पर उपलब्ध है, तो आप फ़ंक्शन को कैश कर सकते हैं, अपना खुद का बना सकते हैं, और इसे अपना कॉल कर सकते हैं।

तो अगर यह मूल है ...

someFunction = function() {
    alert("done");
}

आप ऐसा करेंगे ...

someFunction = (function() {
    var cached_function = someFunction;

    return function() {
        // your code

        var result = cached_function.apply(this, arguments); // use .apply() to call it

        // more of your code

        return result;
    };
})();

यहाँ की बेला है


ध्यान दें कि मैं .applyकैश्ड फ़ंक्शन को कॉल करने के लिए उपयोग करता हूं । यह मुझे अपेक्षित मान को बनाए रखने देता है this, और जो कुछ भी था, उसके बावजूद व्यक्तिगत तर्कों के रूप में जो भी तर्क पारित किए गए थे, उन्हें पारित करते हैं।


10
यह उत्तर वास्तव में शीर्ष एक होना चाहिए - यह प्रश्न में फ़ंक्शन की कार्यक्षमता को संरक्षित करता है ... मेरे से +1।
रीड

17
+1 का उपयोग करने के लिए apply: यह एकमात्र उत्तर है जो वास्तव में समस्या को हल करता है।
lonesomeday

2
@minitech: क्या ... आप जावास्क्रिप्ट के funcitonकीवर्ड से परिचित नहीं हैं ? ;) संपादन के लिए धन्यवाद

1
@gdoron: मैंने अभी एक टिप्पणी जोड़ी है। जब तक मैं अभी वास्तव में अभी उलझन में हूं, मुझे किसी भी ब्राउज़र के बारे में नहीं पता है जो कि वास्तविक तर्क वस्तु को दूसरे arg के रूप में स्वीकार नहीं करेगा .apply()। लेकिन अगर यह उदाहरण के लिए एक jQuery ऑब्जेक्ट की तरह एक ऐरे जैसी वस्तु थी, तो हाँ, कुछ ब्राउज़र एक त्रुटि फेंक देंगे

2
यह उत्तर, जैसा कि होता है, YouTube इफ्रेम एपीआई के माध्यम से एम्बेडेड व्यक्तिगत YouTube वीडियो को नियंत्रित करने के लिए इंस्टेंट ऑब्जेक्ट्स का उपयोग करने की समस्या को हल करता है। आपको पता नहीं है कि कब तक मैं इस तथ्य के इर्द-गिर्द काम करने की कोशिश कर रहा हूं कि एपीआई को एक एकल वैश्विक फ़ंक्शन के लिए कॉलबैक की आवश्यकता होती है, जब मैं एक अद्वितीय मॉड्यूलर तरीके से प्रत्येक वीडियो के डेटा को संभालने के लिए एक वर्ग बनाने की कोशिश कर रहा हूं। आप दिन के लिए मेरे हीरो हैं।
कार्निक्स

31

पहले एक चर में वास्तविक समारोह की दुकान ..

var oldFunction = someFunction;

तो अपने खुद को परिभाषित:

someFunction = function(){
  // do something before
  oldFunction();
  // do something after
};

9
यदि आपका कार्य एक विधि है, तो आपको applyइसे कॉल करने के लिए उपयोग करने की आवश्यकता होगी । देखिए जवाब।
18

इसने मेरे लिए काम किया, लेकिन उपरोक्त कोड के someFunctionसाथ बदलने की आवश्यकता थी window.someFunction। इसका कारण यह है कि मेरे कार्य को एक जॉकरी $(document).ready()हैंडलर के अंदर घोषित किया गया था ।
नेल्सन

10

आप एक फ़ंक्शन बना सकते हैं जो आपके कोड को कॉल करता है, और फिर फ़ंक्शन को कॉल करता है।

var old_someFunction = someFunction;
someFunction = function(){
    alert('Hello');
    old_someFunction();
    alert('Goodbye');
}

6

मुझे नहीं पता कि आप फ़ंक्शन को अपडेट कर सकते हैं, लेकिन यह कैसे संदर्भित किया जाता है इसके आधार पर, आप इसके स्थान पर एक नया फ़ंक्शन बना सकते हैं:

var the_old_function = someFunction;
someFunction = function () {
    /* ..My new code... */
    the_old_function();
    /* ..More of my new code.. */
}

5

इसके अलावा। यदि आप स्थानीय संदर्भ बदलना चाहते हैं तो आपको फ़ंक्शन को फिर से बनाना होगा। उदाहरण के लिए:

var t = function() {
    var a = 1;
};

var z = function() {
    console.log(a);
};

अभी

z() // => log: undefined

फिर

var ts = t.toString(),
    zs = z.toString();

ts = ts.slice(ts.indexOf("{") + 1, ts.lastIndexOf("}"));
zs = zs.slice(zs.indexOf("{") + 1, zs.lastIndexOf("}"));

var z = new Function(ts + "\n" + zs);

तथा

z() // => log: 1

लेकिन यह सिर्फ सबसे सरल उदाहरण है। तर्कों, टिप्पणियों और वापसी मूल्य को संभालने में अभी भी बहुत काम लगेगा। इसके अलावा, अभी भी कई नुकसान हैं।
.String | टुकड़ा | indexOf | lastIndexOf | नया कार्य


1

प्रॉक्सी पैटर्न (जैसा कि user1106925 द्वारा उपयोग किया जाता है) को एक फंक्शन के अंदर रखा जा सकता है। मैंने जो नीचे लिखा था, वह उन कार्यों पर काम करता है जो वैश्विक दायरे में नहीं हैं, और यहां तक ​​कि प्रोटोटाइप पर भी। आप इसे इस तरह उपयोग करेंगे:

extender(
  objectContainingFunction,
  nameOfFunctionToExtend,
  parameterlessFunctionOfCodeToPrepend,
  parameterlessFunctionOfCodeToAppend
)

नीचे दिए गए स्निपेट में, आप मुझे test.prototype.doIt () का विस्तार करने के लिए फ़ंक्शन का उपयोग करके देख सकते हैं।

// allows you to prepend or append code to an existing function
function extender (container, funcName, prepend, append) {

    (function() {

        let proxied = container[funcName];

        container[funcName] = function() {
            if (prepend) prepend.apply( this );
            let result = proxied.apply( this, arguments );
            if (append) append.apply( this );
            return result;
        };

    })();

}

// class we're going to want to test our extender on
class test {
    constructor() {
        this.x = 'instance val';
    }
    doIt (message) {
        console.log(`logged: ${message}`);
        return `returned: ${message}`;
    }
}

// extends test.prototype.doIt()
// (you could also just extend the instance below if desired)
extender(
    test.prototype, 
    'doIt', 
    function () { console.log(`prepended: ${this.x}`) },
    function () { console.log(`appended: ${this.x}`) }
);

// See if the prepended and appended code runs
let tval = new test().doIt('log this');
console.log(tval);

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