JavaScriptファイルにパラメーターを渡す


163

多くの場合、特定の変数をWebページで定義する必要がある、使用したいJavaScriptファイルがあります。

したがって、コードは次のようになります。

<script type="text/javascript" src="file.js"></script>
<script type="text/javascript">
   var obj1 = "somevalue";
</script>

しかし、私がしたいのは:

<script type="text/javascript" 
     src="file.js?obj1=somevalue&obj2=someothervalue"></script>

私はさまざまな方法を試しましたが、最善の方法は次のようにクエリ文字列を解析することです。

var scriptSrc = document.getElementById("myscript").src.toLowerCase();

そして、私の値を検索します。

文字列を解析する関数を作成せずにこれを行う別の方法があるのだろうか。

あなたはみんな他の方法を知っていますか?


9
これは重複した質問(stackoverflow.com/questions/1017424/…)であり、私の意見では誤解されたデザインです。最初の変数ソリューションを使用する(大丈夫)か、変数を使用して呼び出される関数をスクリプトに定義させる(より良い)方がはるかに簡単です。
Matthew Flaschen

新しいECMAScript 6機能を利用する更新されたソリューションを探しています...もしあれば
Chef_Code

サイトがHTTPSで、CSPが完全に有効になっている場合、内部スクリプトを使用すると、CSPレポートがトリガーされます。CSPドキュメントに記載されている理由は、内部要素を許可すると注入が容易になるためです。
デビッドスペクター

回答:


207

可能であれば、グローバル変数を使用しないことをお勧めします。名前空間とOOPを使用して、引数をオブジェクトに渡します。

このコードはfile.jsに属しています。

var MYLIBRARY = MYLIBRARY || (function(){
    var _args = {}; // private

    return {
        init : function(Args) {
            _args = Args;
            // some other initialising
        },
        helloWorld : function() {
            alert('Hello World! -' + _args[0]);
        }
    };
}());

そしてあなたのhtmlファイルで:

<script type="text/javascript" src="file.js"></script>
<script type="text/javascript">
   MYLIBRARY.init(["somevalue", 1, "controlId"]);
   MYLIBRARY.helloWorld();
</script>

4
@Naeem-MYLIBRARY.init(["somevalue"、1、 "controlId"]);のときにfile.jsが100%読み込まれる 実行されますか?多分それを置く準備ができたドキュメントが必要ですか?
Darius.V 2014

2
1)MYLIBRARYが存在する場合は、それを使用するか、新しいオブジェクトを定義します。その目的は、グローバル名前空間を作成することです。通常はサブ名前空間を使用するので、この行はトップレベルの名前空間の再定義を回避するのに役立ちます。2)はい、シングルトンを作成しました。
Naeem Sarfraz、2015

1
このアイデアの例を作成しました:http
//plnkr.co/edit/iE0Vr7sszfqrrDIsR8Wi?p

1
この表現はどういう意味ですか?var MYLIBRARY = MYLIBRARY || (function(){}());?なぜMYLIBRARYブール値に設定する必要があるのですか?
Alex

1
@Alexander、上記の私のコメントを参照stackoverflow.com/questions/2190801/...
Naeem Sarfraz

79

任意の属性を持つパラメーターを渡すことができます。これは最近のすべてのブラウザで機能します。

<script type="text/javascript" data-my_var_1="some_val_1" data-my_var_2="some_val_2" src="/js/somefile.js"></script>

somefile.js内では、次のようにして渡された変数の値を取得できます。

........

var this_js_script = $('script[src*=somefile]'); // or better regexp to get the file name..

var my_var_1 = this_js_script.attr('data-my_var_1');   
if (typeof my_var_1 === "undefined" ) {
   var my_var_1 = 'some_default_value';
}
alert(my_var_1); // to view the variable value

var my_var_2 = this_js_script.attr('data-my_var_2');   
if (typeof my_var_2 === "undefined" ) {
   var my_var_2 = 'some_default_value';
}
alert(my_var_2); // to view the variable value

...等...


1
非常に優れたソリューションで、これは非同期属性でも機能します。
ViRuSTriNiTy 2016年

2
古いがグーグルの場合:これは、CSP(コンテンツセキュリティポリシー)を回避する必要がある場合に最適です。言語リソースやAPIキーなどから決定された文字列をJSファイルに渡す多くのスクリプトを使用しています。
monkeySeeMonkeyDo

2
を使用することもできます。互換性document.currentScriptについてはcaniuse.com/#feat=document-currentscriptを参照してください(またはポリフィルを使用してください)
Yves M.

$(..)構文はjqueryのですが、それを含めることを忘れないでください。
ティモ

48

私が遭遇した別のアイデアはid、を<script>要素に割り当て、引数をdata-*属性として渡すことでした。結果の<script>タグは次のようになります。

<script id="helper" data-name="helper" src="helper.js"></script>

次に、スクリプトはidを使用してプログラムで自分自身を特定し、引数を解析します。前の<script>タグを指定すると、名前は次のように取得できます。

var name = document.getElementById("helper").getAttribute("data-name");

得るname=helper


4
id属性に依存したくない場合は、ページ上のhelper.jsすべてのscriptタグをスクリプトでループさせ、でタグを探しscr="helper.js"、を抽出することもできますdata-name
jvannistelrooy 2014年

1
@jvannistelrooyまだ試していませんが、jqueryと次のような巧妙なセレクターを使用してスクリプトにアクセスできるはずですvar this_js_script = $('script[src*=somefile]');からコピー)
LosManos

19

このURLを確認してください。要件に対して完全に機能しています。

http://feather.elektrum.org/book/src.html

著者に感謝します。クイックリファレンスとして、以下のメインロジックを貼り付けました。

var scripts = document.getElementsByTagName('script');
var myScript = scripts[ scripts.length - 1 ];

var queryString = myScript.src.replace(/^[^\?]+\??/,'');

var params = parseQuery( queryString );

function parseQuery ( query ) {
  var Params = new Object ();
  if ( ! query ) return Params; // return empty object
  var Pairs = query.split(/[;&]/);
  for ( var i = 0; i < Pairs.length; i++ ) {
    var KeyVal = Pairs[i].split('=');
    if ( ! KeyVal || KeyVal.length != 2 ) continue;
    var key = unescape( KeyVal[0] );
    var val = unescape( KeyVal[1] );
    val = val.replace(/\+/g, ' ');
    Params[key] = val;
  }
  return Params;
}

1
私はこのソリューションが好きでしたが、フラグメント識別子を使用するように少し変更して、キャッシュを無効化しませんでした:var frag = myScript.src.replace(/ ^ [^ \#] + \#?/、 '') ;
マークノッティンガム

ああ、私はあなたがそれをurlencodeする限り、そこにJSONを置くことがうまくいくことを発見しました。
マークノッティンガム

@ user378221-これは常に正しいファイルを取得しますか?これは、このファイルが最後であることを前提としています。これが実行される前にスクリプトタグがさらに読み込まれた場合はどうなりますか?それが可能かどうかはわかりませんが、ドキュメントは他のタグをロードするためにコードの実行が完了するのを待たないと思いますか?
Darius.V 2014

unescapeの代わりにdecodeURI()またはdecodeURIComponent()を使用することをお勧めします。その機能は非推奨です。
スティーブチャイルズ、

@ Darius.Vこれは非同期スクリプトでは機能しません。私はオプション1とオプション5をフォールバックとして使用することを好みます
ルーク

14

グローバル変数:-Dを使用します。

このような:

<script type="text/javascript">
   var obj1 = "somevalue";
   var obj2 = "someothervalue";
</script>
<script type="text/javascript" src="file.js"></script">

「file.js」缶アクセス内のJavaScriptコードobj1obj2問題なし。

EDITだけでは、「file.js」のかどうかを確認したい場合ことを追加したいobj1obj2も、あなたは、次の機能を使用することができます宣言されています。

function IsDefined($Name) {
    return (window[$Name] != undefined);
}

お役に立てれば。


IEで参照されないエラーがスローされます。その関数の推奨本体はreturn typeof window[$Name] !== 'undefined';です。その関数に変数の名前を含む文字列を渡すことに注意してください。を介して変数が呼び出し元のコードに存在するかどうかを簡単に確認する方が簡単です(これは関数として実装できません)if (typeof var !== 'undefined')
アンソニーディサンティ2011

2
ああ、IEを使用しないでください。ごめんなさい。
NawaMan、

はい。ただし、JavaScriptの使用経験から、ここに示すように、モジュールの名前空間にのみグローバル変数を使用し、必要なだけ(initコード、一部のプロパティなど)を公開します。複雑なプロジェクトで名前の競合が発生するのは簡単です。何時間もの時間を費やしてから、プロジェクトの他の場所ですでに変数を使用していることがわかります。
マット

省略できvarます。
ティモ

12

これは、非常に急いだ概念実証です。

改善の余地がある場所は少なくとも2つあると確信しています。また、これが実際に長く存続しないことも確信しています。より見やすく、使いやすくするためのフィードバックは大歓迎です。

重要なのは、スクリプト要素のIDを設定することです。唯一の問題は、クエリ文字列をプルするためにそのIDを探すため、スクリプトを一度しか呼び出せないということです。代わりに、スクリプトがすべてのクエリ要素をループしてそれらのいずれかがそれを指しているかどうかを確認し、そうである場合は、そのようなスクリプト要素の最後のインスタンスを使用する場合、これを修正できます。とにかく、コードで:

呼び出されるスクリプト:

window.onload = function() {
//Notice that both possible parameters are pre-defined.
//Which is probably not required if using proper object notation
//in query string, or if variable-variables are possible in js.
var header;
var text;

//script gets the src attribute based on ID of page's script element:
var requestURL = document.getElementById("myScript").getAttribute("src");

//next use substring() to get querystring part of src
var queryString = requestURL.substring(requestURL.indexOf("?") + 1, requestURL.length);

//Next split the querystring into array
var params = queryString.split("&");

//Next loop through params
for(var i = 0; i < params.length; i++){
 var name  = params[i].substring(0,params[i].indexOf("="));
 var value = params[i].substring(params[i].indexOf("=") + 1, params[i].length);

    //Test if value is a number. If not, wrap value with quotes:
    if(isNaN(parseInt(value))) {
  params[i] = params[i].replace(value, "'" + value + "'");
 }

    // Finally, use eval to set values of pre-defined variables:
 eval(params[i]);
}

//Output to test that it worked:
document.getElementById("docTitle").innerHTML = header;
document.getElementById("docText").innerHTML = text;
};

次のページから呼び出されるスクリプト:

<script id="myScript" type="text/javascript" 
        src="test.js?header=Test Page&text=This Works"></script>

<h1 id="docTitle"></h1>
<p id="docText"></p>

したがって、evalは実際に値をグローバル変数として設定します。
rodmjay

1
eval is evil
バリーチャップマン

@barrychapman-おお、2010年。他に10個の赤旗がなかったのには驚きました。
アンソニー

9

とても簡単かもしれません

例えば

<script src="js/myscript.js?id=123"></script>
<script>
    var queryString = $("script[src*='js/myscript.js']").attr('src').split('?')[1];
</script>

次に、クエリ文字列を以下のようにjsonに変換できます

var json = $.parseJSON('{"' 
            + queryString.replace(/&/g, '","').replace(/=/g, '":"') 
            + '"}');

そして、次のように使用できます

console.log(json.id);

6

jQueryのようなJavascriptフレームワークを使用している場合、これは簡単に行うことができます。そのようです、

var x = $('script:first').attr('src'); //Fetch the source in the first script tag
var params = x.split('?')[1]; //Get the params

これで、変数パラメーターとして分割することにより、これらのパラメーターを使用できます。

フレームワークがなくても同じプロセスを実行できますが、さらに数行のコードが必要になります。


2
これをさらに簡単にするparseQueryと呼ばれるjQueryプラグインもあります:plugins.jquery.com/project/parseQuery
Jimmy Cuadra

@JimmyCuadra-残念ながら、提供したリンクは壊れています。しかし、jQuery自体にも同様のアプローチを見つけました。jQuery.param()
Matt

1

まあ、どのスクリプト言語でもjavascriptファイルを作成して、すべてのリクエストで変数をファイルに挿入することもできます。jsファイルを静的に提供しないようにWebサーバーに指示する必要があります(mod_rewriteを使用すれば十分です)。

ただし、これらのjsファイルは絶えず変更されているため、それらのキャッシュが失われることに注意してください。

さようなら。


1
これが反対投票された理由を理解できません。これは、サーバー側のロジックに頼る完全に有効なソリューションです。私の知る限り、OPは完全なJavaScriptソリューションである必要はありません。
2015

@aefxx-あなたは正しい。<script>ブロック内MyModule.Initialize( '<%: Model.SomeProperty%>', '<%: Model.SomeOtherProperty%>', ...);では、サーバー上でレンダリングされるようなものを使用できます。注意:値をエスケープし、値をエスケープ<%:せずに<%=送信します。MyModule名前空間になります(つまり、関数を公開する、自己起動される.jsファイル内の変数Initialize)。役立つ投稿なので、私はあなたの回答を賛成しました。
マット

注:公開されたプロパティが詳細に記載されている含まれているモジュールの作成方法概念、ここにこのページを。
マット

1

素晴らしい質問と独創的な答えですが、私の提案はあなたのメソッドをパラメーター化することであり、それはトリックなしですべての問題を解決するはずです。

機能がある場合:

function A()
{
    var val = external_value_from_query_string_or_global_param;
}

これを次のように変更できます。

function B(function_param)
{
    var val = function_param;
}

これは最も自然なアプローチだと思います。「ファイルパラメータ」に関する追加のドキュメントを作成する必要はなく、同じものを受け取ります。これは、他の開発者にjsファイルの使用を許可する場合に特に役立ちます。


0

いいえ、JSファイルのURLのクエリ文字列部分に変数を追加することで、これを実際に行うことはできません。気になる文字列を解析するコード部分を記述している場合、おそらく別の方法は、jsonで変数をエンコードして、タグのrel属性のようなものに配置することでしょうか?これがあなたが非常に心配しているものであるなら、私はこれがHTML検証の観点からどれほど有効であるかわかりません。次に、スクリプトのrel属性を見つけ、それをjson_decodeするだけです。

例えば

<script type='text/javascript' src='file.js' rel='{"myvar":"somevalue","anothervar":"anothervalue"}'></script>

2
あなたは偽のクエリ文字列でそれを行うことができます。それは単に良い考えではありません。しかし、どちらでもありません。rel属性は、リンク関係のタイプを指定するためのものであり、ランダムなデータをスクリプトタグに詰め込むためのものではありません。
Matthew Flaschen

1
^^同意した。そのままにして、<script> var obj1 = "somevalue" </ script>アプローチを使用することには問題がありません。これが最良の方法であり、正しい方法だと思います。
ダルフンダル

0

これは有効なHTMLではありませんが(私はそうは思いません)、Webページでスクリプトタグのカスタム属性を作成すると機能するようです

<script id="myScript" myCustomAttribute="some value" ....>

次に、JavaScriptのカスタム属性にアクセスします。

var myVar = document.getElementById( "myScript" ).getAttribute( "myCustomAttribute" );

これがスクリプトソース文字列の解析よりも良いか悪いかはわかりません。


0

CSPチェックに合格する方法(安全でないインラインを禁止する)が必要な場合は、nonceメソッドを使用して、スクリプトとCSPディレクティブの両方に一意の値を追加するか、値をhtmlに書き込んで再度読み取る必要があります。

express.jsのノンスメソッド:

const uuidv4 = require('uuid/v4')

app.use(function (req, res, next) {
  res.locals.nonce = uuidv4()
  next()
})

app.use(csp({
  directives: {
    scriptSrc: [
      "'self'",
      (req, res) => `'nonce-${res.locals.nonce}'`  // 'nonce-614d9122-d5b0-4760-aecf-3a5d17cf0ac9'
    ]
  }
}))

app.use(function (req, res) {
  res.end(`<script nonce="${res.locals.nonce}">alert(1 + 1);</script>`)
})

または、htmlメソッドに値を書き込みます。この場合、Jqueryを使用します。

<div id="account" data-email="{{user.email}}"></div>
...


$(document).ready(() => {
    globalThis.EMAIL = $('#account').data('email');
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.