दस्तावेज़ के साथ लिखते समय <स्क्रिप्ट> टैग को क्यों विभाजित करें?


268

कुछ साइटें (या विज्ञापनदाता जो ग्राहकों को जावास्क्रिप्ट कोड देते हैं) कॉल के भीतर <script>और / या </script>टैग को विभाजित करने की एक तकनीक का उपयोग document.write()क्यों करती हैं?

मैंने देखा कि अमेज़ॅन ऐसा करता है, उदाहरण के लिए:

<script type='text/javascript'>
  if (typeof window['jQuery'] == 'undefined') document.write('<scr'+'ipt type="text/javascript" src="http://z-ecx.images-amazon.com/images/G/01/javascripts/lib/jquery/jquery-1.2.6.pack._V265113567_.js"></sc'+'ript>');
</script>

जवाबों:


373

</script>को तोड़ दिया जाना चाहिए क्योंकि अन्यथा यह एन्क्लोज़िंग <script></script>ब्लॉक को बहुत जल्दी समाप्त कर देगा । वास्तव में इसे <और के बीच विभाजित किया जाना चाहिए /, क्योंकि एक स्क्रिप्ट ब्लॉक माना जाता है (एसजीएमएल के अनुसार) किसी भी एंड-टैग ओपन (ईटीएजीओ) अनुक्रम (यानी </) द्वारा समाप्त किया जाना चाहिए :

यद्यपि STYLE और SCRIPT तत्व अपने डेटा मॉडल के लिए CDATA का उपयोग करते हैं, इन तत्वों के लिए, CDATA को उपयोगकर्ता एजेंटों द्वारा अलग तरीके से संभाला जाना चाहिए। मार्कअप और संस्थाओं को कच्चे पाठ के रूप में माना जाना चाहिए और इस तरह से आवेदन करना चाहिए। चरित्र अनुक्रम की पहली घटना " </" (अंत-टैग ओपन सीमांकक) को तत्व की सामग्री के अंत को समाप्त करने के रूप में माना जाता है। वैध दस्तावेजों में, यह तत्व के लिए अंतिम टैग होगा।

हालांकि अभ्यास ब्राउज़रों में केवल एक वास्तविक </script>क्लोज-टैग पर CDATA स्क्रिप्ट ब्लॉक को पार्स करना है ।

XHTML में स्क्रिप्ट ब्लॉक के लिए ऐसी कोई विशेष हैंडलिंग नहीं है, इसलिए उनके अंदर कोई भी <(या &) वर्ण &escaped;किसी अन्य तत्व की तरह होना चाहिए । हालाँकि तब पुराने HTML के रूप में XHTML को ब्राउज़ करने वाले ब्राउज़र भ्रमित हो जाएंगे। सीडीएआरए ब्लॉक में वर्कअराउंड शामिल हैं, लेकिन इन अक्षरों का उपयोग करने से बचने के लिए बस आसान है। स्क्रिप्ट से स्क्रिप्ट तत्व लिखने का एक बेहतर तरीका है जो किसी भी प्रकार के पार्सर पर काम करता है:

<script type="text/javascript">
    document.write('\x3Cscript type="text/javascript" src="foo.js">\x3C/script>');
</script>

30
\/के लिए एक वैध भागने का क्रम है /, तो क्यों न केवल उन स्ट्रिंग शाब्दिक के बजाय का उपयोग करें <? जैसे document.write('<script src=foo.js><\/script>');। इसके अलावा, </script>केवल चरित्र अनुक्रम नहीं है जो किसी <script>तत्व को बंद कर सकता है । यहाँ कुछ और जानकारी: mathiasbynens.be/notes/etago
Mathias Bynens

11
@ माथियास: <\/script>इस मामले में ठीक है, लेकिन यह केवल HTML में काम करेगा; अतिरिक्त CDATA अनुभाग लपेटे बिना XHTML में, यह अभी भी एक अच्छी तरह से गठित त्रुटि है। इसके अलावा, आप \x3Cइनलाइन ईवेंट हैंडलर विशेषताओं का उपयोग कर सकते हैं , <जो HTML और XHTML दोनों में भी अमान्य होगा, इसलिए इसकी व्यापक प्रयोज्यता है: यदि मैं सभी संदर्भों के लिए JS स्ट्रिंग लिटरल में संवेदनशील वर्णों से बचने के लिए एक, आसानी से स्वचालित तरीका चुन रहा था, तो मैं जिस के लिए जाना था।
बॉबिन

3
HTML में, <इनलाइन ईवेंट हैंडलर विशेषताओं का उपयोग किया जा सकता है। html5.validator.nu/… और आप एक HTML की XHTML संगतता के बारे में सही हैं \x3C, लेकिन चूंकि XHTML समर्थन नहीं करता है document.write(या innerHTML) वैसे भी मैं नहीं देखता कि यह कैसे प्रासंगिक है।
मथियास बीनेंस

2
@ MathiasBynens- document.writeअप्रासंगिक है, यह सिर्फ उदाहरण के लिए होता है। ओपी इनरएचटीएमएल का उपयोग कर सकता था, यह </मार्कअप पार्सर से चरित्र अनुक्रम को छिपाने के बारे में है , जहां भी यह होता है। यह सिर्फ इतना है कि अधिकांश पार्सर्स इसे एक स्क्रिप्ट तत्व के अंदर सहन करते हैं जब उन्हें कड़ाई से नहीं करना चाहिए (लेकिन HTML पार्सर बहुत सहनशील होते हैं)। आप सही हैं कि <\/HTML के लिए सभी मामलों में पर्याप्त है।
रोबग

3
मुझे नहीं लगता कि उद्घाटन से बचना <जरूरी है .... document.write('<script src="foo.js">\x3C/script>')IE6 में सभी ब्राउज़रों में पर्याप्त लगता है। (मैंने टाइप विशेषता को छोड़ दिया क्योंकि यह HTML5 में आवश्यक नहीं है, और न ही इसे किसी भी ब्राउज़र द्वारा आवश्यक रूप से लागू किया गया है।)
मैट ब्राउन

34

यहां एक और भिन्नता है जिसका उपयोग मैंने स्क्रिप्ट टैग इनलाइन उत्पन्न करने के लिए किया है (इसलिए यह तुरंत निष्पादित होता है) बिना किसी प्रकार के बचने की आवश्यकता के:

<script>
    var script = document.createElement('script');
    script.src = '/path/to/script.js';
    document.write(script.outerHTML);
</script>

(नोट: नेट पर अधिकांश उदाहरणों के विपरीत, मैं type="text/javascript"न तो एनक्लोजिंग टैग पर सेट कर रहा हूं , और न ही उत्पन्न कोई: ऐसा कोई ब्राउज़र नहीं है जो डिफ़ॉल्ट के रूप में नहीं है, और इसलिए यह बेमानी है, लेकिन या तो चोट नहीं पहुंचेगी, यदि आप असहमत हैं)।


अच्छी बात फिर से: प्रकार। डिफ़ॉल्ट को HTML पाठ के रूप में "टेक्स्ट / जावास्क्रिप्ट" के रूप में परिभाषित किया गया है, इसलिए यह एक बेकार विशेषता है। w3.org/html/wg/drafts/html/master/…
ल्यूक

8
यह स्वीकार किए गए उत्तर से बेहतर है क्योंकि इस बदलाव को वास्तव में छोटा किया जा सकता है। यह 'x3C / स्क्रिप्ट>' मिनिमाइज़ेशन के बाद '</ script>' बन जाएगा।
झूलन कोचन

20

मुझे लगता है कि ब्राउज़र के HTML पार्सर को <स्क्रिप्ट> की व्याख्या करने से रोकना है, और मुख्य रूप से </ script> वास्तविक स्क्रिप्ट के समापन टैग के रूप में, हालांकि मुझे नहीं लगता है कि document.write का उपयोग करना स्क्रिप्ट का मूल्यांकन करने के लिए एक उत्कृष्ट विचार है। ब्लॉक, डोम का उपयोग क्यों नहीं करते ...

var newScript = document.createElement("script");
...

4
यह समय से पहले स्क्रिप्ट ब्लॉक को बंद करने से पार्सर रोकने के लिए आवश्यक है ...
roenving

9

बॉबसन ने जो समाधान पोस्ट किया वह मेरे लिए पूरी तरह से काम करता है। मैं भविष्य के आगंतुकों के लिए एक वैकल्पिक विधि की पेशकश करना चाहता था:

if (typeof(jQuery) == 'undefined') {
    (function() {
        var sct = document.createElement('script');
        sct.src = ('https:' == document.location.protocol ? 'https' : 'http') +
          '://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js';
        sct.type = 'text/javascript';
        sct.async = 'true';
        var domel = document.getElementsByTagName('script')[0];
        domel.parentNode.insertBefore(sct, domel);
    })();
}

इस उदाहरण में, मैंने jQuery के उपयोग के मामले को प्रदर्शित करने के लिए एक सशर्त लोड शामिल किया है। आशा है कि किसी के लिए उपयोगी है!


3
प्रोटोकॉल का पता लगाने की कोई आवश्यकता नहीं है - प्रोटोकॉल-कम यूआरआई ठीक काम करता है ('//foo.com/bar.js' आदि)
dmp

3
Async को सेट करने की कोई आवश्यकता नहीं है। यह सभी गतिशील रूप से बनाए गए स्क्रिप्ट टैग के लिए सेट है।
नोइशे

मुझे बचाया! डॉक्यूमेंट.राइट (<स्क्रिप्ट>) का उपयोग करते समय मेरी साइट एक रिक्त स्क्रीन दिखा रही थी। यह काम किया।
टॉमस गोंजालेज

@dmp को छोड़कर जब फ़ाइल सिस्टम से चल रहा है जहाँ प्रोटोकॉल फ़ाइल होगी: //
mplungjan

9

</script>जावास्क्रिप्ट स्ट्रिंग litteral अंदर एक बंद टैग के रूप में HTML पार्सर द्वारा व्याख्या की है, अनपेक्षित व्यवहार (के कारण JSFiddle पर उदाहरण देखें )।

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

<script type="text/javascript">
    <!--
    if (jQuery === undefined) {
        document.write('<script type="text/javascript" src="http://z-ecx.images-amazon.com/images/G/01/javascripts/lib/jquery/jquery-1.2.6.pack._V265113567_.js"></script>');
    }
    // -->
</script>

... लेकिन ईमानदार होने के लिए, document.writeकुछ ऐसा नहीं है जिसका मैं सबसे अच्छा अभ्यास मानता हूं। डोम को सीधे हेरफेर क्यों नहीं?

<script type="text/javascript">
    <!--
    if (jQuery === undefined) {
        var script = document.createElement('script');
        script.setAttribute('type', 'text/javascript');
        script.setAttribute('src', 'http://z-ecx.images-amazon.com/images/G/01/javascripts/lib/jquery/jquery-1.2.6.pack._V265113567_.js');
        document.body.appendChild(script);
    }
    // -->
</script>

1
); आप शुद्ध जे एस का उपयोग करना चाहते हैं, तो आप अभी भी document.write का उपयोग करना चाहते हैं
नीरव जावेरी

क्षमा करें, मेरा लिखने का मतलब है - इसके लिए jQuery लाइब्रेरी की आवश्यकता है, है ना? जब मैंने उपयोग किया था, document.body.append, यह एक त्रुटि फेंकती है कि document.body.append एक फ़ंक्शन नहीं है।
नीरव झवेरी

1
क्षमा करें, मेरी गलती: मैंने appendइसके बजाय लिखा था appendChild। जवाब सही दिया। ध्यान देने के लिए धन्यवाद!
मैथ्यू रोडिक

1
यह मैन्युअल रूप से स्ट्रिंग को विभाजित करने की तुलना में बहुत अधिक सामान्य दिखता है। यदि स्ट्रिंग को टेम्प्लेट इंजन द्वारा डाला जाता है तो एग विभाजन संभव नहीं है।
w1th0utnam3
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.