我想匹配的只是一个URL的根,而不是一个文本字符串的整个URL。考虑到:

http://www.youtube.com/watch?v=ClkQA2Lb_iE
http://youtu.be/ClkQA2Lb_iE
http://www.example.com/12xy45
http://example.com/random

我想让最后2个实例解析到www.example.com或example.com域。

我听说正则表达式很慢,这将是我在页面上的第二个正则表达式,所以如果有办法做到没有正则表达式,请告诉我。

我正在寻找这个解决方案的JS/jQuery版本。


当前回答

jquery Oneline

$('<a>').attr('href', document.location.href).prop('hostname');

其他回答

解析URL可能很棘手,因为您可以使用端口号和特殊字符。因此,我建议使用parseUri之类的东西来做这个。我怀疑性能不会成为问题,除非您要解析数百个url。

下面是jQuery的一行代码:

$('<a>').attr('href', url).prop('hostname');

我个人对这个解决方案做了很多研究,我能找到的最好的解决方案实际上来自CloudFlare的“浏览器检查”:

function getHostname(){  
            secretDiv = document.createElement('div');
            secretDiv.innerHTML = "<a href='/'>x</a>";
            secretDiv = secretDiv.firstChild.href;
            var HasHTTPS = secretDiv.match(/https?:\/\//)[0];
            secretDiv = secretDiv.substr(HasHTTPS.length);
            secretDiv = secretDiv.substr(0, secretDiv.length - 1);
            return(secretDiv);  
}  

getHostname();

我重写了变量,使它更“人类”可读,但它比预期的工作做得更好。

好吧,我知道这是一个老问题,但我做了一个超级高效的url解析器,所以我想我要分享它。

如你所见,这个函数的结构很奇怪,但这是为了提高效率。不使用原型函数,字符串迭代次数不超过一次,处理字符的次数也不超过必要的次数。

function getDomain(url) {
    var dom = "", v, step = 0;
    for(var i=0,l=url.length; i<l; i++) {
        v = url[i]; if(step == 0) {
            //First, skip 0 to 5 characters ending in ':' (ex: 'https://')
            if(i > 5) { i=-1; step=1; } else if(v == ':') { i+=2; step=1; }
        } else if(step == 1) {
            //Skip 0 or 4 characters 'www.'
            //(Note: Doesn't work with www.com, but that domain isn't claimed anyway.)
            if(v == 'w' && url[i+1] == 'w' && url[i+2] == 'w' && url[i+3] == '.') i+=4;
            dom+=url[i]; step=2;
        } else if(step == 2) {
            //Stop at subpages, queries, and hashes.
            if(v == '/' || v == '?' || v == '#') break; dom += v;
        }
    }
    return dom;
}

不需要解析字符串,只需将URL作为参数传递给URL构造函数:

const url = 'http://www.youtube.com/watch?v=ClkQA2Lb_iE';
const { hostname } = new URL(url);

console.assert(hostname === 'www.youtube.com');