开发者

script tag only run the first time after inserted in the DOM

It is very curious why the script tag only runs once after inserted into the dom.

script = document.createElement('script');
script.type = 'text/javascript'

script
//output: <script type=​"text/​javascript">​</script>​

document.body.appendChild(script);

script.innerHTML = 'console.log("Attempt one")'
//output Attempt one

script.innerHTML = 'console.log("Attempt two")'

script.innerHTML = 'console.log("Attempt three")'

//second and third attempts emit no output

Is there an开发者_高级运维y way to allow the other changes to script text to run?

I've already tried wrap it into a function and no success...I couldn't find any explanation why the log runs the first time and not the following ones


Just to clarify here, that the code above could be a bad approach, etc. But the question really refers to the behaviour and why does it happens.

After playing around in the past minutes I could notice that the javascript will only run once for each script tag once it is both appended to the DOM and has a content.

So for example, you could have a script tag appended to the DOM without any content... that wouldn't fire the javascript. But as soon as you add content to that tag with innerText, innerHTML, etc...it will fire the javascript straight away.

It is quite interesting to notice that each script tag, seems to handle a flag which is set to false every time javascript run for that specific tag, then after this happens it won't fire again, no matter why.

here are some tests that are interesting too:

Normal behaviour

var script = document.createElement('script');

document.body.appendChild(script);

script.innerHTML = 'alert("attemp one")';
// outputs alert
script.innerHTML = 'alert("attemp two")';
// no output

Deep Cloning node

var clone = script.cloneNode(true);
// <script>alert("attemp two")</script>

document.body.replaceChild(clone, script);
// no output

Simple Cloning node

var clone = script.cloneNode();
// <script></script>

clone.innerHTML = 'alert("attemp two")';

document.body.replaceChild(clone, script);
// no output

Replacing for new tag

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

newScript.innerHTML = 'alert("attempt three")';

document.body.replaceChild(newScript, script);
// output alert

So as you can see the script tag will hold the alreadyExecuted attribute no matter why, if you clone it by generating an exact copy or not...

Which makes me think if is there any way to set this flag to its original initial value instead of creating a new script tag.

But in the worst case if you really need to use this. It is not difficult to create an action that will get the script , create a new one with the same attributes if you have some and then replace it with the old but with new content. The javascript would run like the first time.

The following script can easily be called and that will replace the old script tag for a new one and execute the new javascript by simply providing the script tag you wish to replace contents.

function innerScript(element) {

    var newElement = document.createElement('script'),
        attr;

    for (attr = 0; attr < element.attributes.length; attr += 1) {
        newElement.setAttribute(element.attributes[attr].name, element.attributes[attr].value);
    }

    element.parentNode.replaceChild(newElement, element);
    return newElement;

}


just the way it is. you shouldn't generally have to add new code to an existing tag; either create a new tag or make better use of functions and events.


Changing the inner text of the <script /> DOM node at arbitrary points in script execution doesn't trigger the entire script to be re-executed, no.

Create a new script tag or, better, refine your approach. You should never find yourself needing to inject script tags; instead, just execute these function calls in the normal manner.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜