2

So I am a little confounded here. I do not understand why script executes when placed with jquery's .html() but not with innerHTML. I looked at the source code for jQuery's .html and it still seemed that innerHTML was being used. Can anyone explain this behavior?

I came across this during an ajax response. I was getting back html and a script tag with some javascript in it, and I usually use html, but for some reason had used innerHTML this time thinking there was no difference.

I understand that this might seem to be localized, so I made a jsFiddle with a timeout that behaves similar to an ajax response in order to highlight the issue.

jsFiddle demonstrating the behavior

2
  • 1
    The HTML standard explicitly mentions that script elements are not evaluated when set via innerHTML (w3.org/TR/2008/WD-html5-20080610/dom.html#dynamic0): "Note: script elements inserted using innerHTML do not execute when they are inserted." Commented Mar 25, 2013 at 0:01
  • @FelixKling - Thank you for the link. Not sure why I thought otherwise. Commented Mar 25, 2013 at 0:07

1 Answer 1

3

As far as I can tell from a bit of breakpointin', jQuery will try to use innerHTML, but, failing that, it'll fall back to emptying the target element, and appending the new content via the DOM.

Update: see Felix Kling's comment below; basically, if the string content to be inserted contains script or style/link tags, jQuery won't use straight innerHTML

When that happens - and it does in your case - the content goes through a function called domManip which I don't claim to fully understand, but it does specifically look for and evaluate scripts.

So the short answer is: jQuery's not using innerHTML after all. Wish I could give you a better step-by-step of exactly what happens, but I don't know my way around jQuery's source well enough. I just set a breakpoint (at line 6074 in jQuery-1.9.1.js; the point where jQuery decides not to use innerHTML after all) and stepped around the source a little.

Sign up to request clarification or add additional context in comments.

7 Comments

+1 - Good analysis. I noticed that it goes through an interesting process as well but could not for the life of me find where eval would get used in the source code. This answer: stackoverflow.com/a/1197585/1026459 , seems to indicate that eval is used on scripts as well.
@TravisJ yeah, the script content gets passed to globalEval() (see line 597) which does indeed use eval
The test happens in github.com/jquery/jquery/blob/1.9.1/src/manipulation.js#L230. !rnoInnerhtml.test( value ) evaluates to false. At the beginning of the file, it is defined as rnoInnerhtml = /<(?:script|style|link)/i, i.e. it tests for script tags. .append is then used instead, which does what you explained (I didn't look into it any further though).
@FelixKling Ah, that's the trigger. Thanks for clarifying!
@TravisJ No problem, thanks for the checkmark. But I have to say that globalEval() does use actually use eval (see here). No scripts are inserted in the document head (at least not that I can see here in Chrome)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.