如何在JavaScript中拼接相对URL

32
我想在Javascript中连接两个表示相对URL的字符串。 我想将基本URL http://www.adress.com/more/evenmore 与以下示例相结合:
  1. ../../adress(预期输出为:http://www.adress.com/adress
  2. ../adress(预期输出为:http://www.adress.com/more/adress
最好的方法是什么?我考虑使用正则表达式并检查前面有多少个../,然后从baseurl中减去该数量并将其添加到剩下的部分。

1
请考虑更改已接受的答案。 - julealgon
4个回答

85

8年后,许多浏览器(除了Internet Explorer)都支持URL构造函数(URL(url [, base])

> new URL('../address', 'http://www.adress.com/more/evenmore/').href
"http://www.adress.com/more/address"
> new URL('../../address', 'http://www.adress.com/more/evenmore/').href
"http://www.adress.com/address"

这是一个针对IE的polyfill - ashleedawg
5
应该注意,相对路径并不是相对于完整路径而是相对于上一个目录路径。new URL('bar', 'http://example.com/foo) 将导致 http://example.com/bar 而不是 http://example.com/foo/bar - Sukima

14

以下函数将解析URL并进行解析。

function concatAndResolveUrl(url, concat) {
  var url1 = url.split('/');
  var url2 = concat.split('/');
  var url3 = [ ];
  for (var i = 0, l = url1.length; i < l; i ++) {
    if (url1[i] == '..') {
      url3.pop();
    } else if (url1[i] == '.') {
      continue;
    } else {
      url3.push(url1[i]);
    }
  }
  for (var i = 0, l = url2.length; i < l; i ++) {
    if (url2[i] == '..') {
      url3.pop();
    } else if (url2[i] == '.') {
      continue;
    } else {
      url3.push(url2[i]);
    }
  }
  return url3.join('/');
}

1
我修改了你在测试 '.' 的代码,使它也能测试空字符串 url1[i] == '.' || url1[i] == '',因此如果传入的 URL 带有斜杠,它仍将组成一个有效的 URL。+1 - Jay
1
这似乎不像预期的那样工作。/a + ./b = /a/b,但应该是/b。 - Gordon Truslove
@GordonTruslove:也许这可以解决你的问题,它会去掉 aurl1[url1.length-1] = '' - netAction

8

使用URI.js (urijs - npm):absoluteTo()

function joinUrl(baseUrl, url) {
    var theUrl = new URI(url);
    if (theUrl.is("relative")) {
        theUrl = theUrl.absoluteTo(baseUrl);
    }
    return theUrl.toString();
}

现在使用库并不是真正必要的。 - Thomas
3
如果您需要合并相对URL,则此库选项有效。因为ECMAScript的URL会抛出错误: new URL("../the_relative_url", "rel/path/") TypeError: URL constructor: rel/path/不是有效的URL。 - cburgmer
1
我几乎想在你的答案中加上这个。这是一个避免使用URL的很好的理由,特别是在前端,因为Node.js本地模块的访问不受支持。 - Thomas

7
ECMAScript中提到的URL Web API是一个很好的起点,尤其是在原生JS实现(Node等)中可用,并且不需要使用一个库来完成实现已经完成的事情。查阅MDN文档,特别是示例,是一个很好的入门指南。
借鉴(在某种程度上)直接来自于他们的文档:
let m = 'https://developer.mozilla.org';

// ... omitted 

let d = new URL('/en-US/docs', m);

如果你按照上面的做法,然后将构建的URL对象的.toString进行console.log,则输出结果为:'https://developer.mozilla.org/en-US/docs'
值得注意的是,如果您查看文档中的语法部分,您会注意到第二个参数是可选的,并且第二个参数(如上例所示)代表base URL(但仅在提供两个参数的情况下)。
如果两个参数值都是绝对URL,则Web API采用第一个并舍弃第二个。
如果您正在使用Node.js,则应该使用本机的path模块来处理相对路径,而不是使用库。主要动机在于启动您自己的算法(可能只需要调用一下path),这可能比引入可能引入漏洞和不必要的膨胀到应用程序中的多个其他依赖项的库更好,或者仅仅因为它过于沉重而超出了您的需求。
但是,如果您正在前端工作,则无法使用path,并且正如在@cburgmer的答案的评论中提到的那样,Web API的URL不支持所提到的相对路径情况。在这种情况下,您可能需要查找一个库来为您完成此操作。然而,考虑到其他答案,我建议尝试自己编写代码。
值得赞扬的是,URI.js当前仅集成了一项非开发依赖项,并且没有很大占用空间。

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