20

We've been having a discussion at our workplace on this with some for and some against the behavior. Wanted to hear views from you guys :

<html>
<body>
<div>
Test!
<script> document.body.removeChild(document.getElementsByTagName('div')[0]); </script>
</div>
</body>
</html>

Should the above script work and do what it's supposed to do? First, let's see what's happening here :

I have a javascript that's inside the <div> element. This javascript will delete the child node within body which happens to hold the div inside which the script itself exists.

Now, the above script works fine in Firefox, Opera and IE8. But IE6 and IE7 give an alert saying they cannot open the page.

Let's not debate on how IE should have handled this (they've accepted it as a bug and hence fixed it in IE8). The point here is since the 'SCRIPT' tag itself is a part of DOM, should it be allowed to do something like this? Should it even exist after such an operation?

Edit:

Firefox, Opera, IE9 etc. do not remove the 'script' tag if I run the above code. But, document.getElementsByTagName('script').length returns 0!

To understand what I mean, add alert(document.getElementsByTagName('script').length); before and after document.body.removeChild(document.getElementsByTagName('div')[0]); in the code above.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Nischal
  • 958
  • 2
  • 10
  • 14
  • Sure, it's removed itself. Does a defined function in that script area still exist after it's executed? I'm going to assume it will, but you could argue that it shouldn't. – Noon Silk Mar 21 '10 at 06:13
  • A code snippet that deletes itself from the DOM? Sounds a little like a machine whose only purpose is to turn itself off. Like http://sbus.blogspot.com/2008/04/machine-that-turns-itself-off.html or http://techblips.dailyradar.com/video/useless-machine-lego-prototype/ – Tyler Mar 21 '10 at 06:16
  • @Silky Yeah, the function still exists after the script is executed. So, IE9, firefox, Opera and other browsers aren't removing the script tag, which means in a way they aren't considering the script to be a part of DOM, which isn't true since document.getElementsByTagName('script') is supported by them. So, in a way browsers seem to be contradicting themselves, they aren't removing the 'script' tag on dom manipulation but know very well that 'script' is a part of DOM! Are we missing something here? – Nischal Mar 21 '10 at 06:56
  • 5
    It's probably removed by the DOM, but the actual javascript doesn't really exist in the DOM, it exists in the javascript interpreter. I wouldn't say this is really a contradiction, but even if you do, the fact still remains: whatever reason you have for doing this, is probably very wrong – Carson Myers Mar 21 '10 at 07:59

6 Answers6

8

If the question is, "should a script tag be allowed to remove itself?" I would think so. After all, a script tag can cause the browser to navigate to another page, in which case the entire page (including such script tag) is removed from memory.

Will
  • 5,429
  • 4
  • 22
  • 31
  • Well, in the example above, the script tag isn't removed. It still exists, what do you think about that? – Nischal Mar 21 '10 at 06:57
  • When you say "it still exists", do you mean it's still a part of the DOM structure? If so, what is the script element's parent after the div element is removed? – Will Mar 21 '10 at 07:01
  • 1
    Interesting question. Just checked this behavior. If there's only this one 'script' tag then document.getElementsByTagName('script').length gives me a count of 0! But I'm sure the script tag still exists because functions written in that script tag get executed! – Nischal Mar 21 '10 at 07:14
  • 1
    The script tag doesn't "exist" anymore. It's just that the javascript is still loaded in memory. See: http://stackoverflow.com/a/9082798/20801 – Andrew Ensley Jan 22 '14 at 02:01
8

An example where self removal can be handy is, for example, some long polling techniques that would certainly make the DOM large after a few minutes.

JavaScript frameworks add and remove script elements as part of their daily routine.

E.g. getScript() in jQuery places a script tag in the document head and removes it right after evaluation.

They do this to keep the DOM clean - else the tags would just build up unnecessarily. They are no longer needed after evaluation.

The only drawback I see with this is debugging - for example, Firefox with Firebug seems to be lost as to the whereabouts of such scripts and cannot find the source lines. (As of this writing.)

Andras Vass
  • 11,478
  • 1
  • 37
  • 49
6

Actually you can do this:

var currentScript;
currentScript = document.currentScript || document.scripts[document.scripts.length - 1];
currentScript.parentNode.removeChild(currentScript);
edward
  • 71
  • 1
  • 3
  • 1
    Be aware not to use this, when the script tag has `async` or `defer` attribute, because if `currentScript` is not supported the fallback might return another script tag. – RiZKiT Feb 06 '20 at 12:11
2

The script is removing the DIV from the document DOM tree, and just so happens to remove the script declaration itself (after it has been loaded). So I think it should be allowable as a feature.

Also, the script tag will exist until it is loaded and the Javascript is interpreted and executed. At execution, the DIV (and SCRIPT) tag will be removed from the DOM tree and exist only as objects that will be garbage collected.

EDIT

I think the major point here is that a SCRIPT tag only creates the Javascript objects and places them in memory in the Javascript runtime engine (which is completely different from the DOM). Once the interpreter has finished reading the SCRIPT tag, it's no longer needed and can be discarded (removed from the DOM).

If the interpreter was instructed (by the JS code) to create references to OTHER objects in the DOM (e.g. as the handler for a button click), then the Javascript function will still be accessible. Any functions called from that event handler will ALSO be accessible. In this way, you can "walk" the call stack from the button->handler->other functions/variables.

Jeff Meatball Yang
  • 37,839
  • 27
  • 91
  • 125
  • The script isn't removed in the case above. To confirm this, what you can do is create a javascript function just below the code that deletes the child node. Put a button with onclick of the said function. Keep the button in a new div. The onclick still works, I hope your getting what I mean to say here. – Nischal Mar 21 '10 at 06:58
  • 1
    That's true Nischal, but what you've created is a reference from the button in the DOM tree to the function that was created in the now-removed SCRIPT tag... which means that the function still exists in memory and won't be garbage collected. See the MSDN article on why IE doesn't handle this properly. http://msdn.microsoft.com/en-us/library/bb250448(VS.85).aspx – Jeff Meatball Yang Mar 21 '10 at 15:05
1

Yes, it's a valid behavior since script only removes DOM representation of itself. It does not removes itself this way. Actually, script can replace own text representation on the page with something entirely different without being re-run.

Example:

var s = document.createElement('script');
s.textContent = 'alert("Hello, world!");'+
                'document.currentScript.textContent="alert(1)";';
                // BTW, behavior is the same for innerHTML
document.body.appendChild(s);

However, there are almost no valid reasons to make script remove itself or change own code unless you want to keep things in the DOM clean. Also, this won't hide your code from anyone willing to look at it. Usually it means you had to add the script from some other code and it's better to use something like document.body.removeChild(s); from that other script anyway.

Lain inVerse
  • 81
  • 1
  • 4
-2

Using JQuery (over 10.0.1) can make the next:

<!-- you call first to jquery -->
<script id="autoremove">
      $(function(){
           //your operations
                //action
                //action
           //remove the script
           $("#autoremove").remove();
      });
</script>