将参数传递给JavaScript文件

时间:2010-02-03 09:13:23

标签: javascript parameter-passing

我经常会有一个我想要使用的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();

然后搜索我的价值观。

我想知道是否有另一种方法可以在不构建解析字符串的函数的情况下执行此操作。

你们都知道其他方法吗?

16 个答案:

答案 0 :(得分:183)

如果可能,我建议不要使用全局变量。使用命名空间和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>

答案 1 :(得分:63)

您可以传递具有任意属性的参数。这适用于所有最近的浏览器。

<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

...等...

答案 2 :(得分:33)

我遇到的另一个想法是为元素分配一个“id”并将参数作为data- *属性传递。生成的标签看起来像这样:

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

然后,脚本可以使用id以编程方式定位自己并解析参数。给定前一个标记,可以像这样检索名称:

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

我们得到name = helper

答案 3 :(得分:18)

查看此网址。它完全符合要求。

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

答案 4 :(得分:12)

这是一个非常匆忙的概念证据。

我确信至少有两个地方可以改进,而且我也相信这不会在野外存活很久。我们欢迎任何使其更具代表性或可用性的反馈。

关键是为脚本元素设置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>

答案 5 :(得分:10)

您使用全局变量:-D。

像这样:

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

'file.js'中的JavaScript代码可以毫无问题地访问obj1obj2

编辑只想添加,如果'file.js'想检查是否已声明obj1obj2,您可以使用以下功能。

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

希望这有帮助。

答案 6 :(得分: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);

答案 7 :(得分: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

现在,您可以通过拆分作为变量参数来使用这些参数。

可以在没有任何框架的情况下完成相同的过程,但需要更多代码。

答案 8 :(得分:1)

好吧,您可以使用任何脚本语言构建javascript文件,在每次请求时将变量注入文件。您必须告诉您的网络服务器不要静态输出js文件(使用mod_rewrite就足够了)。

请注意,虽然这些js文件经常被更改,但它们会丢失任何缓存。

再见。

答案 9 :(得分:1)

很好的问题和创造性的答案,但我的建议是让你的方法具有典型性,并且应该在没有任何技巧的情况下解决所有问题。

如果你有功能:

function A()
{
    var val = external_value_from_query_string_or_global_param;
}

您可以将其更改为:

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

我认为这是最自然的方法,您不需要创建有关“文件参数”的额外文档,您也会收到相同的信息。如果您允许其他开发人员使用您的js文件,这将特别有用。

答案 10 :(得分:1)

在这里,我找到了另一种做同样事情的方法。在需要的 js 文件 [cttricks.js,因为我用它来测试,你可以拥有任何 .js 文件],我们将简单地列出所有脚本元素并获取所需的元素总是最后一个索引。然后从中获取“.attributes.src.value”。

现在,在任何脚本调用的情况下,都是

<script src="./cttricks.js?data1=Hello&data2=World"></script>

在 cttricks.js 脚本文件中,

var scripts = document.getElementsByTagName('script');
var jsFile = new URL("http://" + scripts[scripts.length-1].attributes.src.value);
/*get value from query parameters*/
console.log(jsFile.searchParams.get("data1"));
console.log(jsFile.searchParams.get("data2"));

享受!!

答案 11 :(得分:0)

不,你不能通过向JS文件URL的查询字符串部分添加变量来实现这一点。如果它编写代码部分来解析困扰你的字符串,或许另一种方法是json编码你的变量并把它们放在像标签的rel属性这样的东西上?我不知道这在HTML验证方面是多么有效,如果那是你非常担心的事情。然后你只需要找到脚本的rel属性,然后找到json_decode。

例如

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

答案 12 :(得分:0)

它不是有效的html(我不认为)但是如果你为网页中的脚本标签创建自定义属性,似乎可以工作:

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

然后访问javascript中的自定义属性:

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

不确定这是否比解析脚本源字符串更好或更差。

答案 13 :(得分:0)

如果您需要通过CSP检查的方式(禁止不安全的内联),则必须使用nonce方法向脚本和CSP指令添加唯一值,或将值写入html并再次读取它们。

express.js的Nonce方法:

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

答案 14 :(得分:0)

尽管这个问题已经问了一段时间,但到今天仍然有用。这不是使用脚本文件参数的简单方法,但是我已经有了一些最适合这种方式的极端用例。

我偶然发现了这篇文章,以找到比我之前写的更好的解决方案,希望找到本机功能或类似功能。
我将分享我的解决方案,直到实施更好的解决方案为止。在大多数现代浏览器(即使是较旧的浏览器)上也无法使用。

以上所有解决方案均基于以下事实,即必须注入预定义且标记明确的SCRIPT标签,并且完全依赖HTML实现。但是,如果脚本是动态注入的,或者更糟糕的是,如果您正在编写将在各种网站中使用的库,该怎么办?
在这些以及其他一些情况下,以上所有答案都是不够的,甚至变得太复杂了。

首先,让我们尝试了解我们在这里需要实现的目标。我们需要做的就是从那里获取脚本本身的URL。

实际上有一个很好的技巧,可以从脚本本身获取脚本URL。本机Error类的功能之一是能够提供“问题位置”的堆栈跟踪,包括到最后一次调用的确切文件跟踪。为了实现这一点,我将使用Error实例的stack属性,该属性一旦创建,便会给出完整的堆栈跟踪。

这是魔术的工作原理:

// The pattern to split each row in the stack trace string
const STACK_TRACE_SPLIT_PATTERN = /(?:Error)?\n(?:\s*at\s+)?/;
// For browsers, like Chrome, IE, Edge and more.
const STACK_TRACE_ROW_PATTERN1 = /^.+?\s\((.+?):\d+:\d+\)$/;
// For browsers, like Firefox, Safari, some variants of Chrome and maybe other browsers.
const STACK_TRACE_ROW_PATTERN2 = /^(?:.*?@)?(.*?):\d+(?::\d+)?$/;

const getFileParams = () => {
    const stack = new Error().stack;
    const row = stack.split(STACK_TRACE_SPLIT_PATTERN, 2)[1];
    const [, url] = row.match(STACK_TRACE_ROW_PATTERN1) || row.match(STACK_TRACE_ROW_PATTERN2) || [];
    if (!url) {
        console.warn("Something went wrong. You should debug it and find out why.");
        return;
    }
    try {
        const urlObj = new URL(url);
        return urlObj.searchParams; // This feature doesn't exists in IE, in this case you should use urlObj.search and handle the query parsing by yourself.
    } catch (e) {
        console.warn(`The URL '${url}' is not valid.`);
    }
}

现在,在任何脚本调用情况下,例如在OP情况下:

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

file.js脚本中,您现在可以执行以下操作:

const params = getFileParams();
console.log(params.get('obj2'));
// Prints: someothervalue

这也将与RequireJS和其他动态注入的文件脚本一起使用。

答案 15 :(得分:0)

我认为在包含 javascript 的页面上使用 localStorage 然后在 javascript 本身内部重新使用它是更好和现代的解决方案。将其设置在 localStorage 中:

localStorage.setItem("nameOfVariable", "some text value");

并在 javascript 文件中引用它,例如:

localStorage.getItem("nameOfVariable");