使用 javascript 将脚本附加到头部 - 奇怪的行为 [英] Appending scripts to head using javascript - weird behavior

查看:34
本文介绍了使用 javascript 将脚本附加到头部 - 奇怪的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要解决的问题是一个广告加载脚本,它使用 jsonp 加载广告代码并将其插入到 dom 中.

现在有时广告代码会包含 javascript 标签,我认为只需将它们移动到 head 部分,它们就会运行.理论上这很好用,但是当我制作一个脚本将脚本标签移动到头部时,我遇到了一些奇怪的行为.

所以我写了这段代码只是为了测试脚本移动部分,消除了作为错误源的其余代码.

我得到相同的结果,如果我在 div 中只有两个脚本,它会移动其中一个,如果我有 3 个脚本,它会移动其中的 2 个.在下面粘贴的代码中,它移动了脚本 1 和 3,跳过了远程 javascript 引用和最后一个脚本标记.

至少知道为什么会发生这种情况以及是否可以解决会很有趣.

为了澄清一件事,如果我首先放置远程 jquery 脚本,然后放置一个简单的脚本标签,它会将远程脚本标签移动到头部并跳过第二个脚本标签.

<头><script type="text/javascript">//获取 div id功能测试() {var td = document.getElementById('testId');var 脚本 = td.getElementsByTagName("script");console.log("传输到头部的脚本数量:"+scripts.length);for(i=0;i<scripts.length;i++) {var curScript = 脚本 [i];document.head.appendChild(curScript);}}<body onload="test();"><div id="testId"><script type="text/javascript">var firstScript = 1;</script><script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script><script type="text/javascript">var secondScript = 1;</script><script type="text/javascript">varthirdScript = 1;</script>

解决方案

你在一个错误的假设下工作:script 元素是否在 head<中并不重要/code> 或 body,它们无论如何都会运行.在它们被附加到 DOM 之后移动它们充其量是毫无意义的,最坏的情况是如果在移动时重新运行脚本可能会导致不幸的副作用(但我认为不是).

至于为什么您会看到您所看到的行为,这是因为 getElementsByTagName 返回一个 live NodeList.当您移动脚本时,它会从 NodeList 中删除.所以给定你的四个脚本,你会得到一个 NodeList 最初包含四个元素,所以 .length4[0] 是你的第一个脚本.当您将该脚本移出 div 时,NodeList 会更新,因为脚本不再位于 div 中,因此它的长度现在是3[0] 指的是你的第二个脚本(加载 jQuery 的那个).

您可以通过两种方式避免这种行为中断您的循环:

  1. 向后循环,从 .length - 10(含),或

  2. NodeList 变成一个数组,这样元素就不会从你下面移出.

The problem I'm trying to solve is an ad loading script, that loads the ad code with jsonp and inserts it into the dom.

Now sometimes the ad code will include javascript tags, and i figured it was just a matter of moving them to the head section and they would run. In theory that works fine but when i made a script to move script tags to the head i ran into some weird behavior.

So I wrote this code to test just the script moving part, eliminating the rest of the code as an error source.

I get the same results, if I have just two scripts in the div it moves one of them, if I have 3 scripts it moves 2 of them. In the code pasted below it moves script 1 and 3, skipping the remote javascript reference and the last script-tag.

Would be interesting to at least know why this happens, and if it can be solved.

Edit: To clarify one thing, if i put the remote jquery script first and one of the simple script tags second it will move the remote script tag to the head fine and skip the second script tag.

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
// get div id
function test() {
var td = document.getElementById('testId');
var scripts = td.getElementsByTagName("script");
console.log("No. of scripts to transfer to head: "+scripts.length);
for(i=0;i<scripts.length;i++) {
    var curScript = scripts[i];
    document.head.appendChild(curScript);
}   
}
</script>
</head>
<body onload="test();">
<div id="testId">
    <script type="text/javascript">var firstScript = 1;</script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <script type="text/javascript">var secondScript = 1;</script>
    <script type="text/javascript">var thirdScript = 1;</script>
</div>
</body>
</html>

解决方案

You're laboring under a false assumption: It doesn't matter whatsoever whether script elements are in the head or body, they get run regardless. Moving them after they've been appended to the DOM is at best pointless, and at worst may cause unfortunate side-effects if the script is re-run when moved (but I don't think it is).

As for why you're seeing the behavior you're seeing, it's because getElementsByTagName returns a live NodeList. When you move a script, it gets removed from the NodeList. So given your four scripts, you'll get back a NodeList initially containing four elements, so .length is 4 and [0] is your first script. When you move that script out of the div, the NodeList is updated because the script is no longer in the div, so its length is now 3 and [0] refers to your second script (the one loading jQuery).

You can avoid having this behavior interrupt your loop in two ways:

  1. Loop backward, from .length - 1 to 0 inclusive, or

  2. Turn the NodeList into an array, so the elements aren't moved out from under you.

这篇关于使用 javascript 将脚本附加到头部 - 奇怪的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆