你知道为什么下面这段代码没有将脚本元素添加到DOM中吗?

var code = "<script></script>";
$("#someElement").append(code);

我曾见过一些浏览器在你直接执行某些更改时不尊重它们的问题(我指的是从文本创建HTML,就像你尝试使用script标记一样),但当你使用内置命令执行这些更改时,事情会变得更好。试试这个:

var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.src = url;
$("#someElement").append( script );

来自:JSON for jQuery


你说“不工作”是什么意思?

jQuery检测到您正在尝试创建一个SCRIPT元素,并将自动在全局上下文中运行元素的内容。你是说这对你没用吗?-

$('#someElement').append('<script>alert("WORKING");</script>');

编辑:如果你在运行命令后没有在DOM中看到SCRIPT元素(例如在Firebug中),这是因为jQuery,就像我说的,将运行代码,然后将删除SCRIPT元素-我相信SCRIPT元素总是附加到主体…但无论如何,在这种情况下,位置对代码执行完全没有影响。


我想做同样的事情,但附加一个脚本标签在其他框架!

var url = 'library.js'; 
var script = window.parent.frames[1].document.createElement('script' ); 
script.type = 'text/javascript'; 
script.src = url;
$('head',window.parent.frames[1].document).append(script);

<script>
    ...
    ...jQuery("<script></script>")...
    ...
</script>

字符串字面值中的</script>终止整个脚本,以避免使用“</scr”+“ipt>”代替。


可以使用jQuery函数getScript动态加载JavaScript文件

$.getScript('http://www.whatever.com/shareprice/shareprice.js', function() {
  Display.sharePrice();
});

现在外部脚本将被调用,如果不能加载它,它将优雅地降级。


如此:

$('body').append($("<script>alert('Hi!');<\/script>")[0]);

jQuery似乎在脚本上做了一些聪明的事情,所以你需要附加html元素而不是jQuery对象。


好消息是:

100%有效。

只需在脚本标记中添加一些内容,例如alert('voila!');。您可能想问的正确问题是,“为什么我在DOM中没有看到它?”

Karl Swedberg在jQuery API网站上对访问者的评论做了一个很好的解释。我不想重复他所有的话,你可以直接在这里阅读(我发现很难浏览那里的评论)。

All of jQuery's insertion methods use a domManip function internally to clean/process elements before and after they are inserted into the DOM. One of the things the domManip function does is pull out any script elements about to be inserted and run them through an "evalScript routine" rather than inject them with the rest of the DOM fragment. It inserts the scripts separately, evaluates them, and then removes them from the DOM. I believe that one of the reasons jQuery does this is to avoid "Permission Denied" errors that can occur in Internet Explorer when inserting scripts under certain circumstances. It also avoids repeatedly inserting/evaluating the same script (which could potentially cause problems) if it is within a containing element that you are inserting and then moving around the DOM.

接下来,我将通过使用.append()函数添加一个脚本来总结坏消息。


坏消息是…

你不能调试代码。

我不是在开玩笑,即使你添加了调试器;关键字,你将最终只得到对象的调用堆栈,而看不到源代码上的断点,(更不用说这个关键字只适用于webkit浏览器,所有其他主流浏览器似乎都省略了这个关键字)。

如果您完全理解您的代码是做什么的,那么这将是一个小缺点。但如果你不这样做,你最终会添加一个调试器;关键字到处都是,只是为了找出你(或我)的代码有什么问题。不管怎样,还有另一种选择,不要忘记javascript可以原生操作HTML DOM。


解决方案。

使用javascript(而不是jQuery)来操作HTML DOM

如果您不想失去调试功能,那么您可以使用javascript原生HTML DOM操作。想想这个例子:

var script   = document.createElement("script");
script.type  = "text/javascript";
script.src   = "path/to/your/javascript.js";    // use this for linked script
script.text  = "alert('voila!');"               // use this for inline script
document.body.appendChild(script);

就在那里,就像过去一样,不是吗。不要忘记清理DOM或内存中所有被引用且不再需要的对象,以防止内存泄漏。你可以考虑下面的代码来清理:

document.body.removechild(document.body.lastChild);
delete UnusedReferencedObjects; // replace UnusedReferencedObject with any object you created in the script you load.

这种解决方法的缺点是可能会不小心添加重复的脚本,这很糟糕。从这里开始,您可以稍微模仿.append()函数,在添加之前添加对象验证,并在添加脚本后立即从DOM中删除脚本。想想这个例子:

function AddScript(url, object){
    if (object != null){
        // add script
        var script   = document.createElement("script");
        script.type  = "text/javascript";
        script.src   = "path/to/your/javascript.js";
        document.body.appendChild(script);

        // remove from the dom
        document.body.removeChild(document.body.lastChild);
        return true;
    } else {
        return false;
    };
};

function DeleteObject(UnusedReferencedObjects) {
    delete UnusedReferencedObjects;
}

这样,您可以添加带有调试功能的脚本,同时避免脚本重复。这只是一个原型,你可以把它扩展成任何你想要的样子。我一直在使用这种方法,并对此非常满意。果然,我永远不会使用jQuery .append()来添加脚本。


在脚本文件中添加sourceURL会有帮助,如本页所述: https://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/

在脚本文件中,添加一个带有sourceURL的语句,如"//@ sourceURL=foo.js" 使用jQuery $.getScript()加载脚本,脚本将在chrome开发工具的“sources”选项卡中可用


你的脚本正在执行,你只是不能使用文档。从它写。使用警报来测试它,避免使用document.write。js文件中的语句与document。Write将不执行,函数的其余部分将执行。


试试这个可能会有帮助:

var fileref=document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src","scriptAnalytics.js");
document.getElementsByTagName("head")[0].appendChild(fileref);

将脚本追加到正文:

$(document).ready(function() {
    $("<script>", {  src : "bootstrap.min.js",  type : "text/javascript" }).appendTo("body");
});

这是我认为最好的解决办法。谷歌分析就是这样注入的。

var (function(){
    var p="https:" == document.location.protocol ? "https://" : "http://";
        d=document,
        g=d.createElement('script'),
        s=d.getElementsByTagName('script')[0];
        g.type='text/javascript';
        g.src=p+'url-to-your-script.js';
        s.parentNode.insertBefore(g,s); })();

如果想要追加代码,另一种方法是使用文档。createElement方法,但使用。innerhtml而不是。src。

var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.innerHTML = 'alert("Hey there... you just appended this script to the body");';
$("body").append( script );

只需通过jQuery解析来创建一个元素。

<div id="someElement"></div>
<script>
    var code = "<script>alert(123);<\/script>";
    $("#someElement").append($(code));
</script>

工作示例:https://plnkr.co/edit/V2FE28Q2eBrJoJ6PUEBz


你不需要jQuery来创建一个Script DOM元素。它可以用香草ES6这样做:

const script = "console.log('Did it work?')"
new Promise((resolve, reject) => {
  (function(i,s,o,g,r,a,m){
      a=s.createElement(o),m=s.getElementsByTagName(o)[0];
      a.innerText=g;
      a.onload=r;m.parentNode.insertBefore(a,m)}
  )(window,document,'script',script, resolve())
}).then(() => console.log('Sure did!'))

它不需要包装在Promise中,但是这样做允许您在脚本加载时解析Promise,有助于防止长时间运行的脚本出现竞争条件。


我试过这个,效果很好。只需将<符号替换为\x3C。

// With Variable
var code = "\x3Cscript>SomeCode\x3C/script>";
$("#someElement").append(code);

or

//Without Variable
$("#someElement").append("\x3Cscript>SomeCode\x3C/script>");

您可以在这里测试代码。


可以这样试试

var code = "<script></" + "script>";
$("#someElement").append(code);

你不能做“<script></script>”的唯一原因是因为字符串在javascript中是不允许的,因为DOM层不能解析什么是js什么是HTML。


我写了一个npm包,它可以让你在执行脚本时将HTML字符串(包括脚本标签)附加到容器中

例子:

import appendHtml from 'appendhtml';

const html = '<p>Hello</p><script src="some_js_file.js"></script>'; 
const container = document.getElementById('some-div');

await appendHtml(html, container);

// appendHtml returns a Promise, some_js_file.js is now loaded and executed (note the await)

在这里找到它:https://www.npmjs.com/package/appendhtml