189

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

然后搜索我的价值观。

我想知道是否有另一种方法可以在不构建函数来解析我的字符串的情况下做到这一点。

大家知道其他方法吗?

4

17 回答 17

226

如果可能,我建议不要使用全局变量。使用命名空间和 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>
于 2010-02-03T09:33:20.760 回答
92

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

<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

...ETC...

于 2013-02-25T14:28:40.963 回答
68

我遇到的另一个想法是将 an 分配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

于 2013-07-16T13:21:47.560 回答
20

看看这个网址。它完美地满足了要求。

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;
}
于 2010-06-28T16:28:55.470 回答
17

您使用全局变量:-D。

像这样:

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

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

编辑只是想补充一点,如果'file.js'想要检查是否obj1甚至obj2已经被声明,你可以使用以下函数。

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

希望这可以帮助。

于 2010-02-03T09:19:10.270 回答
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>
于 2010-02-03T11:15:59.097 回答
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, '":"') 
            + '"}');

然后可以使用like

console.log(json.id);
于 2016-03-01T11:27:48.423 回答
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

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

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

于 2010-02-03T09:20:05.620 回答
2

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

请注意,您会丢失这些 js 文件的任何缓存,因为它们会不断更改。

再见。

于 2010-02-03T09:21:51.637 回答
1

很好的问题和有创意的答案,但我的建议是让你的方法参数化,这应该可以解决你所有的问题,而无需任何技巧。

如果你有功能:

function A()
{
    var val = external_value_from_query_string_or_global_param;
}

您可以将其更改为:

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

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

于 2010-06-28T16:53:50.080 回答
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"));

享受!!

于 2021-03-26T16:07:05.113 回答
0

不,您不能通过将变量添加到 JS 文件 URL 的查询字符串部分来真正做到这一点。如果它编写代码部分来解析困扰你的字符串,也许另一种方法是对你的变量进行 json 编码并将它们放在标签的 rel 属性中?我不知道这在 HTML 验证方面有多有效,如果那是您非常担心的事情。然后你只需要找到脚本的 rel 属性,然后 json_decode 。

例如

<script type='text/javascript' src='file.js' rel='{"myvar":"somevalue","anothervar":"anothervalue"}'></script>
于 2010-02-03T09:25:11.617 回答
0

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

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

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

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

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

于 2013-04-11T15:31:27.617 回答
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');
}
于 2019-12-06T06:02:10.257 回答
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和其他动态注入的文件脚本。

于 2020-07-24T17:49:42.760 回答
0

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

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

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

localStorage.getItem("nameOfVariable");
于 2021-02-19T16:27:19.540 回答
0

可以将参数传递给 js 模块并在 via 之后读取它们import.meta.url

例如,使用以下 HTML

<script type="module">
import './index.mjs?someURLInfo=5';
</script>

以下 JavaScript 文件将记录 someURLInfo 参数:

// index.mjs
new URL(import.meta.url).searchParams.get('someURLInfo'); // 5

当一个文件导入另一个文件时也是如此:

// index.mjs
import './index2.mjs?someURLInfo=5';

// index2.mjs
new URL(import.meta.url).searchParams.get('someURLInfo'); // 5
于 2022-01-03T20:03:19.947 回答