How jQuery .html() Executes Inline Script Tags
When developers use jQuery’s .html() method to insert
markup containing inline <script> tags, jQuery
automatically extracts and executes the JavaScript code within the
global scope. Unlike native DOM methods such as
Element.innerHTML—which explicitly block script execution
for security reasons—jQuery intercepts HTML strings, separates the
script elements, appends the standard markup to the DOM, and dynamically
executes the script content.
Native innerHTML
vs. jQuery .html()
In standard HTML5, inserting markup through
element.innerHTML = "<script>alert('test');</script>"
will not run the script. This behavior was implemented by browser
vendors to reduce cross-site scripting (XSS) risks.
jQuery's .html() method was designed to make dynamic DOM
updates intuitive, which historically meant ensuring that any included
scripts ran as developers expected. To achieve this, jQuery circumvents
native browser suppression by parsing and executing scripts
manually.
Step 1: Parsing Markup and Isolating Scripts
When you pass an HTML string containing script tags to
.html(val), jQuery processes the string through internal
utilities:
- Document Fragment Creation: jQuery parses the HTML
string into DOM nodes using a temporary
DocumentFragment. - Identification and Extraction: jQuery traverses the
generated nodes to locate all
<script>elements, whether they reference external sources (src) or contain inline code. - Detachment: jQuery removes these script elements from the fragment before injecting the remaining HTML into the target element. This ensures that non-script elements are rendered in the DOM first.
Step 2: Global Execution via Script Injection
Once the non-script DOM elements are appended to the document, jQuery iterates over the extracted script elements in the exact order they appeared.
For inline scripts, jQuery does not rely on standard
eval(), because direct eval() runs within the
local function scope. Instead, jQuery ensures the code runs in the
global window scope using an internal utility called
jQuery.globalEval().
In modern jQuery versions, global evaluation is achieved by:
- Creating a new, native
<script>DOM element viadocument.createElement("script"). - Assigning the inline code string to the new element's
.textproperty. - Appending this temporary script element directly to
document.head. - Immediately removing the script element from
document.headviaparentNode.removeChild().
Because the script node is appended to the active DOM document, the browser's JavaScript engine immediately parses and executes the inline code in the global execution context. Removing the node right afterward cleans up the DOM while leaving the side effects (such as defined functions or global variables) intact in memory.
Scope, Order, and Execution Characteristics
- Global Scope: Variables declared with
varor traditional function declarations inside the inline script are attached to the globalwindowobject, matching standard page-load script behavior. - Synchronous Execution: Inline scripts are evaluated synchronously in the order they were defined within the markup string.
- Cleaned DOM: Because jQuery handles execution through this temporary injection pattern, the script tags themselves may not remain in the final target element's DOM tree, depending on the exact jQuery version and methods used.