从“GET”参数中获取值(JavaScript)

1727

我有一个带有GET参数的URL,如下所示:

www.test.com/t.html?a=1&b=3&c=m2-m3-m4-m5 

我需要获取整个 c 的值。我尝试读取URL,但我只得到了 m2 。如何使用JavaScript实现这一点?


9
在发表新回答之前,请考虑已经有50多个回答了。请确保您的回答提供的信息不在现有的答案中。 - janniks
var url_string = "http://www.example.com/t.html?a=1&b=3&c=m2-m3-m4-m5"; //window.location.href var url = new URL(url_string); var c = url.searchParams.get("c"); console.log(c); - Ali NajafZadeh
1
真是疯狂,一个本应该很简单的JS问题需要50多个答案 :/ - fguillen
63个回答

2669

JavaScript本身没有内置处理查询字符串参数的功能。

在(现代)浏览器中运行的代码可以使用 URL 对象(一个Web API)进行操作。 URL也被Node.js实现:

// You can get url_string from window.location.href if you want to work with
// the URL of the current page
var url_string = "http://www.example.com/t.html?a=1&b=3&c=m2-m3-m4-m5"; 
var url = new URL(url_string);
var c = url.searchParams.get("c");
console.log(c);


对于旧版浏览器(包括Internet Explorer),您可以使用此polyfill

您还可以使用URLSearchParams,并提取查询字符串以通过window.location.search.substring(1)来传递。


您也可以使用先前版本的答案中的代码(早于URL)。 上述polyfill非常强大且经过充分测试,因此我强烈建议使用它而不是使用这个方法。

您可以访问location.search,它会给您提供从?字符到URL结尾或片段标识符(#foo)开头的内容,取决于哪个先出现。

然后可以使用以下方式进行解析:

function parse_query_string(query) {
  var vars = query.split("&");
  var query_string = {};
  for (var i = 0; i < vars.length; i++) {
    var pair = vars[i].split("=");
    var key = decodeURIComponent(pair.shift());
    var value = decodeURIComponent(pair.join("="));
    // If first entry with this name
    if (typeof query_string[key] === "undefined") {
      query_string[key] = value;
      // If second entry with this name
    } else if (typeof query_string[key] === "string") {
      var arr = [query_string[key], value];
      query_string[key] = arr;
      // If third or later entry with this name
    } else {
      query_string[key].push(value);
    }
  }
  return query_string;
}

var query_string = "a=1&b=3&c=m2-m3-m4-m5";
var parsed_qs = parse_query_string(query_string);
console.log(parsed_qs.c);

你可以使用以下代码从当前页面的URL中获取查询字符串:

var query = window.location.search.substring(1);
var qs = parse_query_string(query);

对于旧版浏览器,除了为 URLSearchParams 添加 polyfill 之外,您可能还需要一个 polyfill for URL。或者,您可以通过将上面答案中的行 var c = url.searchParams.get("c"); 替换为 var c = new URLSearchParams(window.location.search).get("c"); 来避免这个问题。 - evanrmurphy
@Snowmanzzz — localhost: 不是一个有效的 URL。http://localhost/path?query=something 是有效的。http://localhost:80/path?query=something 也是有效的。URL 对象可以很好地处理它们。 - Quentin
哇,即使在前端专属页面上,这也非常有用:您只需共享带参数的链接,并使用此代码预加载一些变量以生成特定的共享视图。 - Foxcode

268

我见过的大多数实现都忽略了对名称和值进行URL解码。

这里是一个通用的实用函数,也可以进行正确的URL解码:

function getQueryParams(qs) {
    qs = qs.split('+').join(' ');

    var params = {},
        tokens,
        re = /[?&]?([^=]+)=([^&]*)/g;

    while (tokens = re.exec(qs)) {
        params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
    }

    return params;
}

//var query = getQueryParams(document.location.search);
//alert(query.foo);

5
这段代码无法正常运行。它会创建一个无限循环,因为在循环定义中编译了正则表达式,导致当前索引重置。如果将正则表达式放在循环外的变量中,则可以正常工作。 - maxhawkins
4
在一些浏览器中,它可以正常运行,而在其他浏览器中则会进入无限循环。在这方面,你是半对的。我将修复代码以支持跨浏览器。感谢你指出这一点! - Ates Goral
4
这个函数应该用于URL的查询部分,而不是整个URL。请参见下面的已注释的使用示例。 - Ates Goral
2
@Harvey 不区分大小写不是查询参数的关注点。这听起来像是一个特定于应用程序的事情,应该与查询参数提取一起或在其之上应用。 - Ates Goral
8
为什么使用qs.split('+').join(' ');而不是qs.replace(/\+/g, ' ');? - FlameStorm
显示剩余6条评论

261

来源

function gup( name, url ) {
    if (!url) url = location.href;
    name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
    var regexS = "[\\?&]"+name+"=([^&#]*)";
    var regex = new RegExp( regexS );
    var results = regex.exec( url );
    return results == null ? null : results[1];
}
gup('q', 'hxxp://example.com/?q=abc')

9
我最喜欢这个选项,但更倾向于返回 null 或结果,而不是一个空字符串。 - Jason Thrasher
2
看起来你有一些额外的转义字符。 "\[" 应该是 "\["。由于它们是常规字符串,所以 [ 和 ] 不需要转义。 - EricP
这不是大小写不敏感的。我应该在哪里添加“i”以使其大小写不敏感? - zeta
alert(gup('UserID', window.location.href)); --> 警告(gup('UserID',window.location.href)); - Arun Prasad E S
如果URL中没有参数,结果将为Null并生成错误。在尝试解析数组之前测试是否为null可能更好。 - Antony P.
显示剩余2条评论

250

这是一个简单的方法来检查一个参数:

示例 URL:

http://myserver/action?myParam=2

示例 Javascript:

var myParam = location.search.split('myParam=')[1]

如果URL中存在"myParam",变量myParam将包含"2",否则它将是未定义的。

也许你想要一个默认值,在这种情况下:

var myParam = location.search.split('myParam=')[1] ? location.search.split('myParam=')[1] : 'myDefaultValue';

更新: 这个方法效果更好:

var url = "http://www.example.com/index.php?myParam=384&login=admin"; // or window.location.href for current url
var captured = /myParam=([^&]+)/.exec(url)[1]; // Value is in [1] ('384' in our case)
var result = captured ? captured : 'myDefaultValue';

即使 URL 充满参数,它也能正常工作。


47
只有当你获取的参数是URL中最后一个参数时,这种方法才有效,但你不应该依赖于这一点(即使你只期望一个参数)。例如,"http://myserver/action?myParam=2&anotherParam=3"将返回"2&anotherParam=3"而不是"2"。请注意,这种方法可能会导致意想不到的结果。 - Benjamin Carlsson
47
(适用于多个参数或可能丢失myParam的情况)(location.search.split('myParam =')[1] ||'').split('&') [0] - Gábor Imre
2
location.search.split('myParam=').splice(1).join('').split('&')[0] - J.Steve
2
你可以通过在参数前加上 [?|&],例如 [?|&]myParam=([^&]+),来获得更高的精度并允许任意顺序的参数。 - 1.21 gigawatts
2
你可能需要解码值 result = decodeURIComponent(result); - 1.21 gigawatts
当我尝试运行这段代码时,它可以工作,但是我的电脑过一会儿就会冻结。 - Mustafa Demir

159

浏览器厂商已经通过URL和URLSearchParams提供了一个本地方法来实现这一点。

let url = new URL('http://www.test.com/t.html?a=1&b=3&c=m2-m3-m4-m5');
let searchParams = new URLSearchParams(url.search);
console.log(searchParams.get('c'));  // outputs "m2-m3-m4-m5"

目前在Firefox、Opera、Safari、Chrome和Edge中得到支持。有关浏览器支持列表请参见此处

https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams https://developer.mozilla.org/en-US/docs/Web/API/URL/URL

https://url.spec.whatwg.org/

Google工程师Eric Bidelman 推荐使用这个polyfill来支持不受支持的浏览器。


3
@Markouver 难道不是 polyfill 处理这个问题吗?顺便说一句,Safari 就是现代版的 IE6。 - Csaba Toth
为什么 new URLSearchParams("www.test.com/t.html?a=1&b=3&c=m2-m3-m4-m5").get('a') 在 Chrome 稳定版中返回 null?似乎 bc 的工作正常。 - ripper234
什么版本?最新的吗? - cgatian
7
请使用 url.searchParams 替代 new URLSearchParams(url.search) - Caio Tarifa
@CaioTarifa,该属性在窗口上不存在。 - cgatian
显示剩余8条评论

107

我很久以前就发现了这个,非常简单:

function getUrlVars() {
    var vars = {};
    var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi,    
    function(m,key,value) {
      vars[key] = value;
    });
    return vars;
  }

然后像这样调用:

var fType = getUrlVars()["type"];

简短 + 简单 + 强大 = 伟大 - mzy
2
非常好,它也可以使用location.search而不是window.location.href来工作。 - Fabio C.
2
@pdxbmw这个代码是无用的,应该被删除。看起来可能很聪明,但并没有经过深思熟虑的考虑。改进:对值使用decodeURIComponent(),因为这通常是您想要处理的内容;使用window.location.search而不是window.location.href,因为您只对参数感兴趣,而不是整个URL。 - Leif
我在我的ES6项目中使用了它:decodeURIComponent(window.location.search).replace(/[?&]+([^=&]+)=([^&]*)/g, (m, key, value) => params[key] = value); - Yao
3
@Leif的建议非常有效。我遇到了一个问题,因为在URL末尾生成了一个#号,导致我得到了ID 142#。将该函数保留为以下形式:var vars = {}; window.location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { vars[key] = value; }); return vars;即可解决问题。请注意,这里并没有修改原文的意思。 - Andres Ramos
显示剩余2条评论

83

您可以通过 location.search 获取查询字符串,然后将问号后的所有内容拆分开:

var params = {};

if (location.search) {
    var parts = location.search.substring(1).split('&');

    for (var i = 0; i < parts.length; i++) {
        var nv = parts[i].split('=');
        if (!nv[0]) continue;
        params[nv[0]] = nv[1] || true;
    }
}

// Now you can get the parameters you want like so:
var abc = params.abc;

4
对于参数名和值进行URL解码如何? - Ates Goral
这种方法无法处理数组。例如,?array[]=1&array[]=2 会产生 {"array[]": "2"} 的结果,显然是错误的。 - Kafoso
2
@Kafoso 这里并没有明确的对错。首先,具有相同名称的重复字段没有指定的标准行为,由解析器处理。此外,“[]”模式在某些情况下(例如PHP)才有意义,而在其他情况下则没有意义。因此,并非“明显错误”,只是未实现以处理非标准情况,而这是否需要处理取决于您的需求。 - Blixt

54

使用 URLSearchParams 的超级简单方法。

function getParam(param){
  return new URLSearchParams(window.location.search).get(param);
}

目前它在Chrome、Firefox、Safari、Edge和其他浏览器中得到支持。


在Edge中运行时,出现错误:“SCRIPT5009:未定义'URLSearchParams'”。 - Andreas Presthammer
@AndreasPresthammer 你使用的是哪个版本的Edge? - spencer.sm
@spencer-sm 微软 Edge 41.16299.820.0 - Andreas Presthammer
@iiiml0sto1,“美化的URL参数”是什么? - spencer.sm

39

我写了一个更简单、更优雅的解决方案。

var arr = document.URL.match(/room=([0-9]+)/)
var room = arr[1];

看这个,只有两行代码,完全按照描述的功能运行 - 并且不会因为有人试图探测漏洞并添加大量额外字符和查询而崩溃,这点比其他几个解决方案要好。感谢你啊! - David G
这个做得很好,而且只用了两行代码。非常棒的答案! - Andres Ramos
我认为如果包含了检查空值的功能,那对其他人来说会很方便。如果没有,可以参考这个示例:https://dev59.com/EXNA5IYBdhLWcg3wZ85R#36076822(我的编辑尝试被拒绝了)。 - atw
聪明,但它到底“在罐子上”说了什么?在我看来,它似乎只能处理参数包含数字的情况,并且无法处理OP的问题,其中参数为m2-m3-m4-m5? - Tom Warfield
它也匹配 noroom=1234,这是不可取的。 - Izhar Aazmi
显示剩余2条评论

34

这是一个递归的解决方案,没有正则表达式,并且只有最小限度的改变(仅参数对象被改变,我认为在JS中无法避免)。

它很棒,因为它:

  • 是递归的
  • 处理同名的多个参数
  • 能很好地处理格式错误的参数字符串(缺少值等)
  • 如果在值中有 "=",也不会出现问题
  • 执行URL解码
  • 最后,它很棒,因为......哎呀!

代码:

var get_params = function(search_string) {

  var parse = function(params, pairs) {
    var pair = pairs[0];
    var parts = pair.split('=');
    var key = decodeURIComponent(parts[0]);
    var value = decodeURIComponent(parts.slice(1).join('='));

    // Handle multiple parameters of the same name
    if (typeof params[key] === "undefined") {
      params[key] = value;
    } else {
      params[key] = [].concat(params[key], value);
    }

    return pairs.length == 1 ? params : parse(params, pairs.slice(1))
  }

  // Get rid of leading ?
  return search_string.length == 0 ? {} : parse({}, search_string.substr(1).split('&'));
}

var params = get_params(location.search);

// Finally, to get the param you want
params['c'];

32
你说了两次"recursive"。 - Dissident Rage
无法在下一个URL中找到第一个参数:www.mysite.com?first=1&second=2 - Mario Radomanana
嗨,Mario,这里有一个JSFiddle演示它与该URL一起工作:http://jsfiddle.net/q6xfJ/ - 如果您发现错误,这可能是特定于浏览器的吗?在测试时,请注意我提供的答案使用location.search,即URL的“?first=1&second=2”部分。干杯 :) - Jai
48
我不认为仅因为它是递归的就一定好。 - Adam Arold
8
嗯,亚当,我觉得你错过了递归笑话。不过现在因为edi9999删掉了第二个“Is recursive”,所以每个人都会错过它。 - Jai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接