- Асинхронні скрипти async and defer
- Атрибут Type
- integrity
- Crossorigin
- document.currentScript
- onafterscriptexecute
- for / event
- NOSCRIPT
- Тег Script і innerHTML
01 липня 2016
Як ви, напевно, знаєте, тег Script використовується для підключення JavaScript, який повинен бути запущений на сторінці. Тег сценарію може або включати безпосередньо JavaScript код, або вказувати на URL, звідки сценарій повинен бути завантажений.
Теги виконуються в порядку їх появи. Це повинно бути інтуїтивно зрозуміло, коли ви читаєте цей код:
<Script> var x = 3; </ Script> <script> alert (x); // Will alert '3'; </ Script>
Це менш інтуїтивно (але не менше вірно) при роботі з зовнішніми ресурсами.
<Script src = \ "// typekit.com/fj3j1j2.js \"> </ script> <script src = \ "// my.site/script.js \"> </ script>
Це аналогічно працює для комбінацій локальних і віддалених сценаріїв.
Функціонально це означає, що ви можете істотно сповільнити ваш сайт, якщо у вас є повільні сценарії із завантаженням на початку сторінки. Це також означає, що сценарії, які з'являються пізніше на сторінці, можуть залежати від елементів сценаріїв, які виконалися раніше.
Елементи на сторінці не будуть відображатися, поки все теги сценарію, що передують їм, що не буде завантажено і не виконуватися. Тобто, ви можете змінити сторінку, перш ніж вона завантажиться, якщо ви готові пожертвувати продуктивністю. Це не відноситься, до додавання тега в DOM після того, як сторінка початку завантажуватися за допомогою document.appendChild або чогось подібного. Ці теги будуть завантажуватися щоразу, коли браузер вважатиме за потрібне, і в довільному порядку.
Коли сценарій виконується, є тільки те, що знаходиться над ним в DOM.
<Html> <head> <script> // document.head is available // document.body is not! </ Script> </ head> <body> <script> // document.head is available // document.body is available </ script> </ body> </ html>
Ви можете подумати про HTML-аналізаторі, як про проходження по документу тег за тегом, по ходу виконуючи всі JavaScript. Це означає, що DOM вузли доступні для вашого JavaScript (через querySelectorAll, JQuery і т.п.), тільки якщо їх тег з'являється в документі раніше, ніж тег сценарію.
Корисним наслідком цього є те, що document.head доступний практично завжди, в будь-якому JavaScript, а document.body доступний тільки якщо ваш скрипт знаходиться всередині тега або після body.
Асинхронні скрипти async and defer
HTML5 додав пару інструментів для управління виконанням сценаріїв:
- Async означає \ "виконати це в будь-який час \". Більш конкретно це означає: Мені все одно, що ви виконуєте це після того, як вся сторінка була завантажена, і всі інші сценарії були виконані. Це дуже корисно для кодів аналітики відстеження, так як ніякий інший код на сторінці не залежить від їх виконання. Визначення важливою змінною або функції в async коді - це погана ідея, тому що ви дійсно не знаєте, коли саме він спрацює.
- Defer означає \ "чекати аналізатор, щоб закінчити і виконати \". Це приблизно рівнозначно підв'язці сценарію до події DOMContentLoaded або використання jQuery.ready. Коли код виконується, все в DOM буде доступно для використання. На відміну від async, defer код буде працювати по порядку, в якому він розташований на HTML сторінці, він просто відкладається до тих пір, поки HTML не буде повністю проаналізовано.
Атрибут Type
Історично (з часів Netscape 2), було абсолютно неважливо, вказали ви type = \ "text / javascript \" в тегах сценарію або просто залишили його порожнім. Якщо ви встановили якийсь тип MIME, який не є різновидом JavaScript як type, браузер все одно не буде виконувати його. Це може бути здорово, коли ви хочете визначити свою власну мову:
<Script type = \ "text / emerald \"> make a social network but for cats </ script>
Фактичне виконання цього коду залежить від вас, тобто, ви можете використовувати щось на зразок цього:
<Script> var codez = document.querySelectorAll ( 'script [type = \ "text / emerald"]'); for (var i = 0; i <codez.length; i ++) runEmeraldCode (codez [i] .innerHTML); </ Script>
Якщо у вас з'явиться таке бажання, ви можете також перевизначити тип за замовчуванням для кожного сценарію на сторінці, використовуючи тег meta:
<Meta http-equiv = \ "Content-Script-Type \" content = \ "text / vbscript \">
Або заголовок Content-Script-Type.
integrity
Атрибут integrity є частиною нової специфікації Subresource. Він дозволяє отримати хеш контенту, який містить файл сценарію. Це корисно для запобігання зміни вмісту тега script ззовні. У світі SSL, це необхідно, якщо ви завантажуєте скрипт з зовнішнього джерела, який ви не контролюєте, наприклад, code.jquery.com.
Якщо ви вирішите використовувати цей інструмент, ви повинні вказати тип хеша який ви використовуєте, і значення хеша, розділивши їх дефісом. Це виглядає наступним чином:
<Script src = \ "// code.jquery.com/jquery.js \" integrity = \ "sha384-oqVuAfXRKap7fdgcCY5uykM6 + R9GqQ8K / uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC \"> </ script>
Crossorigin
Він не повністю стандартизований, але підтримується деякими браузерами. Основна ідея полягає в тому, що браузер не любить дозволяти вам розпоряджатися ресурсами, завантаженими ні з поточної сторінки, а з іншого \ "джерела \". (Походження визначається як поєднання протоколу, імені хоста і порту сторінки. Тобто http://google.com:80).
Його зв'язок з тегами сценарію кілька умовна. Ідея полягає в тому, що якщо застосувати обробник до події window.onerror, цей обробник забезпечується деякою інформацією про сторінку і сценарії якщо ви завантажуєте код з зовнішнього сайту. У захищених браузерах ця інформація не передається, якщо не визначено crossorigin.
Crossorigin НЕ магічний хак безпеки, він всього лише дозволяє налаштувати браузер, щоб виконати CORS перевірку доступу на запит OPTIONS і перевірку заголовків Access-Control.
document.currentScript
Він не підтримується IE, що трохи знижує його ефективність, але властивість document.currentScript вказує на поточний виконується сценарій. Це може бути дуже корисно, якщо ви хочете витягнути атрибути з поточного тега script.
onafterscriptexecute
Це супер-марна річ, тому що вона підтримується тільки Firefox. Цей атрибут поряд з onbeforescriptexecute дозволяє вказати подія, яке буде виконуватися до і після кожного сценарію на сторінці, що, в загальному корисно.
Якщо вам цікаво, об'єкти подій включають в себе посилання на виконуваний сценарій, тому подія before може скасувати виконання за допомогою preventDefault ().
for / event
На сьогоднішній день в специфікації HTML5 включені рідкісні, специфічні IE методи прив'язки коду до події. Ви можете використовувати це, щоб тег сценарію не виконувався, поки сторінка не завантажиться:
<Script for = \ "window \" event = \ "onload \"> alert (\ "Hi! \") </ Script>
NOSCRIPT
У це важко повірити, але колись JavaScript був ще молодий. Був час, коли ви не могли бути впевнені, чи буде даний браузер коректно виконувати JavaScript чи ні. Що ще гірше, ви не могли бути впевнені в тому, що браузер буде знати, що таке тег script. І якщо браузер не розпізнає тег, він повинен зробити його рядковим елементом, тобто весь JavaScripts буде показаний на сторінці як текст!
На щастя, специфікація змогла забезпечити рішення, яке дозволяє інтерпретувати як HTML-коментар все те, що не підтримує браузер:
<Script> <! - to hide script contents from old browsers // You would probably be pasting a 'rollover' script // you got from hotscripts.net here // end hiding contents from old browsers -> </ script>
Звичайно, як і більшість речей, XHTML зробив це набагато гірше. XML має дуже специфічний метод приховування контенту, який може включати в себе закривання тегів та інше. Так народився CDATA:
<Script> // <! [CDATA [// Is this the right incantation to get this to pass // the XHTML validator? //]]> </ script>
Природно, якщо ваш код буде дійсним XHTML, це не матиме ніякого впливу на його функціональність, але це неймовірно важливо для вашої самооцінки як веб-розробника.
Браузери також містять корисну функцію, що дозволяє користувачам, у яких не включений JavaScript, перейти на тег NoScript. NoScript обертає контент, який повинен відображатися, тільки якщо браузер не підтримує виконання сценаріїв:
<Noscript> Please use Internet Explorer 5.5 or above. </ Noscript> <script> exploitInternetExplorer0Day (); </ Script>
Якщо ви спостережливі, ви зрозумієте, що NoScript не приймає аргумент type, що робить його взаємодія зі сторінками, які використовують кілька типів сценаріїв кілька неоднозначним. Фактичне поведінка варіюється від браузера до браузеру.
Тег Script і innerHTML
І наостанок, дозвольте розповісти про одну кумедну особенності.Тегі Script, які динамічно додаються на сторінку за допомогою DOM, виконуються в браузері:
var myScript = document.createElement ( 'script'); myScript.textContent = 'alert (\ "✋ \")'; document.head.appendChild (myScript);
А теги, які динамічно додаються на сторінку за допомогою innerHTML, не виконуються:
document.head.innerHTML + = '<script> alert (\ "✋ \") </ script>';
Чому? Невідомо, але це забавний відповідь на питання, чи можна в інспектора відобразити скрипт, який фактично не виконується.
CDATA [// Is this the right incantation to get this to pass // the XHTML validator?