<script>要素を追加できません


276

以下のコードがスクリプト要素をDOMに追加しない理由は何ですか?

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

4
「機能していない」と定義します。ただし、問題はスクリプトが実際にはdomツリーの一部ではないことだと思います。
Joel Coehoorn 2009年

1
私の考えでは、スクリプトノードがDOMに追加されていますが、ブラウザはスクリプトを実行していません。
アウトロープログラマー

ダン、実際にこれをどのようにテストしましたか?
ジェームズ

1
@Joel-"動作していません" =効果がありません。つまり、スクリプト内のコードが実行されません@Outlaw Programmer-ノードがDOMに追加されていません@Jimmyはい、私はテストしましたが動作していません
Danブルゾ

回答:


259

一部のブラウザでは、直接変更したときに一部の変更が尊重されない(つまり、スクリプトタグで試行しているようなテキストからHTMLを作成する)が、組み込みコマンドで変更すると問題が発生する物事はうまくいきます。これを試して:

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

From:jQueryのJSON


18
<script>タグは、既存の要素のinnerHTMLではなく、DOM自体に追加する必要があります。
Diodeus-James MacFarlane 2009年

6
@Diodeus innerHTMLはDOMの一部であり、ブラウザによってその場で解析されるため、これは有効なケースです。
クリスティアントマ


5
要素をDOMに表示したい場合は、jQueryの追加を使用しないでください。これを行うには、ネイティブのappendChildを使用します。
Minqi Pan

8
$("#someElement")[0].appendChild( script );
Minqi Pan

352

良いニュースは:

100%機能しています。

のようなスクリプトタグ内に何かを追加するだけalert('voila!');です。右の質問はあなたがおそらく聞きしたい場合があり、「なぜ私はDOMでそれを見ていません?」

Karl SwedbergがjQuery APIサイトの訪問者のコメントに良い説明をしました。私はしませんあなたが直接読み取ることができ、すべての彼の言葉を繰り返したい、ここで(私はそこにコメントをナビゲートするハード、それを発見しました)

jQueryのすべての挿入メソッドは、内部でdomManip関数を使用して、DOMに挿入される前後に要素をクリーンアップ/処理します。domManip関数が行うことの1つは、挿入しようとしているスクリプト要素を引き出して、DOMフラグメントの残りを挿入するのではなく、「evalScriptルーチン」を介して実行することです。スクリプトを個別に挿入して評価し、DOMから削除します。

jQueryがこれを行う理由の1つは、特定の状況でスクリプトを挿入するときにInternet Explorerで発生する可能性がある「アクセスが拒否されました」エラーを回避するためだと思います。また、挿入してDOM内を移動する包含要素内にある場合、同じスクリプトを繰り返し挿入/評価すること(これにより問題が発生する可能性があります)も回避されます。

次は、.append()スクリプトを追加する関数を使用して、悪い点をまとめます。


そして悪いニュースは..

コードをデバッグすることはできません。

冗談ではありません。debugger;ブレークポイントとして設定する行の間にキーワードを追加しても、ソースコードにブレークポイントが表示されずに、オブジェクトのコールスタックのみが取得されます(これは言うまでもありません)キーワードはwebkitブラウザーでのみ機能します。他のすべての主要ブラウザーはこのキーワードを省略しているようです)

コードの機能を完全に理解している場合は、これがマイナーな欠点になります。しかし、そうしないと、debugger;あなた(または私の)のコードのどこに問題があるのか​​を見つけるために、キーワードをあちこちに追加することになります。とにかく、代替手段があります。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;
}

このようにして、スクリプトの重複から保護しながら、デバッグ機能を備えたスクリプトを追加できます。これは単なるプロトタイプであり、好きなように拡張できます。私はこのアプローチを使用しており、これに非常に満足しています。確か.append()に、jQuery を使用してスクリプトを追加することは決してありません。


2
素晴らしい説明、ありがとう!しかし、「UnusedReferencedObjects」だったのでしょうか?
acme

ありがとう。ロードしたスクリプトで作成したオブジェクトであるはずの「UnusedReferencedObjects」の最初の出現を参照していたと思います。DeleteObject関数の機能を確認すると、関数に渡されたオブジェクトがすべて削除されるだけで理解が深まると思います。明確にするために、コードにコメントを追加します。:)
Hendra Uzia

スーパーポスト!aCrosmanの例ではうまくいきませんでした。投稿の準備ができたら、$( "#someElement")。append(script);を置き換えました。$( "#someElement")[0] .appendChild(script); それはそれを修正しました:)外植のためのThnx
Maarten Kieft

7
$.getScriptjQueryに組み込まれています。
zzzzBov

SourceURLs(blog.getfirebug.com/2009/08/11/…)は、問題のデバッグに役立つ場合があります。
vsevik

23

jQuery関数を使用してJavaScriptファイルを動的にロードすることが可能ですgetScript

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

これで外部スクリプトが呼び出され、ロードできない場合は正常に機能しなくなります。


7
これはDOMに何も挿入しません。と呼びますeval()
nh2

20

「機能しない」とはどういう意味ですか?

jQueryは、SCRIPT要素を作成しようとしていることを検出し、グローバルコンテキスト内で要素のコンテンツを自動的に実行します。これはあなたにとってうまくいかないと私に言っていますか?-

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

編集:私が言ったようにjQueryがコードを実行してSCRIPT要素を削除するため、コマンドを実行した後、DOMにSCRIPT要素が表示されていない場合(たとえばFirebugで)、SCRIPT要素を信じています常にボディに追加されます...しかし、とにかく-この状況では、配置はコード実行にまったく影響しません。


17

これは機能します:

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

jQueryはスクリプトを巧妙に処理しているようですので、jQueryオブジェクトではなくhtml要素を追加する必要があります。


2
これが私の場合に機能する唯一のソリューションです。上記の他の解決策は、htmlファイルに事前に存在するJavaScriptコードに依存します。私は動的にコードを追加しているので、そのようなJavaScriptコードを事前に知ることはできません!ありがとうダーウィン!
tgoneil 2013年

14

これは役立つかもしれません:

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

9
なぜこの男がネガティブなのは、jqueryをすべてに使用し続けるのに十分なほど愚かでない唯一の人なのか、わかりません!
SSpoke、2014年

質問ではOPがjQueryを使用しているため、おそらくほとんどの回答はjQueryを使用しています。
sanbor

3

同じことをしたいのですが、他のフレームにスクリプトタグを追加します!

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);

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

</script>文字列リテラル内では避けるために、スクリプト全体を終了させる"</scr" + "ipt>"代わりに使用することができます。


または、JavaScriptをHTMLドキュメント内に直接埋め込まないでください。外部スクリプトファイルにはこの問題はありません。
Ian Clelland、2010

エスケープシーケンス:"\x3cscript\x3e\x3c/script\x3e"。XHTMLでは、コメントアウトされたCDATAブロックを配置するだけです。
イーライグレイ

2
それはむしろ</許されないことです。stackoverflow.com/questions/236073/…を
Gumbo

2

スクリプトファイルにsourceURLを追加すると、このページで説明したように役立ちました。https://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/

  1. スクリプトファイルで、 "// @ sourceURL = foo.js"のようなsourceURLを含むステートメントを追加します。
  2. jQuery $ .getScript()を使用してスクリプトをロードすると、スクリプトはChrome開発ツールの[ソース]タブで利用可能になります

1

あなたのスクリプトは実行中です、あなたdocument.writeはそれから使うことができません。アラートを使用してテストし、の使用を避けdocument.writeます。jsファイルのステートメントはdocument.write実行されず、関数の残りの部分が実行されます。


1

これが私が最良の解決策だと思うものです。Google Analyticsはこの方法で注入されます。

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); })();

1

スクリプトDOM要素を作成するためにjQueryは必要ありません。これは、バニラ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、これにより、スクリプトのロード時にプロミスを解決できるため、長時間実行されるスクリプトの競合状態を回避できます。



0

コードを追加したい場合に実行できるもう1つの方法は、document.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 );

0

私はこの試みたものを、細かい動作します。<シンボルをそれで置き換えてください\x3C

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

または

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

ここでコードをテストできます


0

このように試すことができます

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

あなたができない唯一の理由"<script></script>"は、DOMレイヤーがjsとHTMLを解析できないため、JavaScript内では文字列が許可されないためです。


0

私が書いた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


-1

jQueryで解析して要素を作成するだけです。

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

作業例:https : //plnkr.co/edit/V2FE28Q2eBrJoJ6PUEBz


これにはまだ同じ問題があり、一部のブラウザはこれを尊重しません。
マーティンマッセラ2017年

使用しているブラウザとjQueryのバージョンを教えてください。ありがとう!
sanbor 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.