简体   繁体   中英

new URL(location.href) doesn't work in IE

I am facing to problem with method new URL('address') in IE.

I have this code:

var href =  location.href;
var hrefParams = new URL(href);
var api = hrefParams.searchParams.get("api");

In Firefox and Chrome it works at should and I will get the value of attribute "api".

But in IE I am getting error on console:

SCRIPT445: Object doesn't support this action

Console error debugger points to the problem with line

var hrefParams = new URL(href);

For solving of another problem I already invoking script

<script type="text/javascript" src="js/bluebird.min.js"></script>

But it doesn't fix this problem.

Any idea how to fix it in IE?

At the end I have fixed that by this code:

function getQueryString() {
          var key = false, res = {}, itm = null;
          // get the query string without the ?
          var qs = location.search.substring(1);
          // check for the key as an argument
          if (arguments.length > 0 && arguments[0].length > 1)
            key = arguments[0];
          // make a regex pattern to grab key/value
          var pattern = /([^&=]+)=([^&]*)/g;
          // loop the items in the query string, either
          // find a match to the argument, or build an object
          // with key/value pairs
          while (itm = pattern.exec(qs)) {
            if (key !== false && decodeURIComponent(itm[1]) === key)
              return decodeURIComponent(itm[2]);
            else if (key === false)
              res[decodeURIComponent(itm[1])] = decodeURIComponent(itm[2]);
          }

          return key === false ? res : null;
}

...

        var api = getQueryString('api');

I forgot where I found that but it is working as I needed.

IE does not support URL . You will have to add a polyfill for it.

Another solution I've been using if anyone is interested

function getParameterByName(name) {
  name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
  var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
      results = regex.exec(location.search);
  return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}

getParameterByName('api');

添加polyfill cdn 脚本

<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>

This method is not supported by IE

See https://developer.mozilla.org/en-US/docs/Web/API/URL#AutoCompatibilityTable

you should use a lib like jquery deparam or retrieve the parameters with String.split() method or use this function that I made:

 function decodeUriComponentWithSpace (component) { return decodeURIComponent(component.replace(/\+/g, '%20')) } // type : 'hash', 'search' or 'both' function getLocationParameters (location, type) { if (type !== 'hash' && type !== 'search' && type !== 'both') { throw 'getLocationParameters expect argument 2 "type" to be "hash", "search" or "both"' } let searchString = typeof location.search === 'undefined' ? '' : location.search.substr(1) let hashString = typeof location.hash === 'undefined' ? '' : location.hash.substr(1) let queries = [] if (type === 'search' || type === 'both') { queries = queries.concat(searchString.split('&')) } if (type === 'hash' || type === 'both') { queries = queries.concat(hashString.split('&')) } let params = {} let pair for (let i = 0; i < queries.length; i++) { if (queries[i] !== '') { pair = queries[i].split('=') params[this.decodeUriComponentWithSpace(pair[0])] = this.decodeUriComponentWithSpace(pair[1]) } } return params } // TEST: window.location.hash = 'test=a&test2=b' console.log(getLocationParameters(window.location, 'both'))

Pure Javascript solution, so you can run it in IE as well without bothering with polyfills:

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

Comes from this page:https://html-online.com/articles/get-url-parameters-javascript/

For the purposes of my project, I've created this script, which I think also could work for you or someone else who has a problem with IE11 and the lack of support for the URL method.

        /* Polyfill URL method IE 11 */

        // ES5

        if (typeof window.URL !== 'function') {
            window.URL = function (url) {
                var protocol = url.split('//')[0],
                    comps = url.split('#')[0].replace(/^(https\:\/\/|http\:\/\/)|(\/)$/g, '').split('/'),
                    host = comps[0],
                    search = comps[comps.length - 1].split('?')[1],
                    tmp = host.split(':'),
                    port = tmp[1],
                    hostname = tmp[0];

                search = typeof search !== 'undefined' ? '?' + search : '';

                var params = search
                    .slice(1)
                    .split('&')
                    .map(function (p) { return p.split('='); })
                    .reduce(function (p, c) {
                        var parts = c.split('=', 2).map(function (param) { return decodeURIComponent(param); });
                        if (parts.length == 0 || parts[0] != param) return (p instanceof Array) && !asArray ? null : p;
                        return asArray ? p.concat(parts.concat(true)[1]) : parts.concat(true)[1];
                    }, []);

                return {
                    hash: url.indexOf('#') > -1 ? url.substring(url.indexOf('#')) : '',
                    protocol: protocol,
                    host: host,
                    hostname: hostname,
                    href: url,
                    pathname: '/' + comps.splice(1).map(function (o) { return /\?/.test(o) ? o.split('?')[0] : o; }).join('/'),
                    search: search,
                    origin: protocol + '//' + host,
                    port: typeof port !== 'undefined' ? port : '',
                    searchParams: {
                        get: function(p) {
                            return p in params? params[p] : ''
                        },
                        getAll: function(){ return params; }
                    }
                };
            }
        }

        // ES6, in case of using Babel in a project

        if( typeof window.URL !== 'function' ){
            window.URL = function(url){
                let protocol = url.split('//')[0],
                    comps = url.split('#')[0].replace(/^(https\:\/\/|http\:\/\/)|(\/)$/g, '').split('/'),
                    host = comps[0],
                    search = comps[comps.length - 1].split('?')[1],
                    tmp = host.split(':'), 
                    port = tmp[1], 
                    hostname = tmp[0];

                search = typeof search !== 'undefined'? '?' + search : '';

                const params = search
                                    .slice(1)
                                    .split('&')
                                    .map(p => p.split('='))
                                    .reduce((obj, pair) => {
                                        const [key, value] = pair.map(decodeURIComponent);
                                        return ({ ...obj, [key]: value })
                                    }, {});

                return {
                    hash: url.indexOf('#') > -1? url.substring(url.indexOf('#')) : '',
                    protocol,
                    host,
                    hostname,
                    href: url,
                    pathname: '/' + comps.splice(1).map(function(o){ return /\?/.test(o)? o.split('?')[0] : o; }).join('/'),
                    search,
                    origin: protocol + '//' + host,
                    port: typeof port !== 'undefined'? port : '',
                    searchParams: {
                        get: p => p in params? params[p] : '',
                        getAll: () => params
                    }
                };
            }
        }
        /* Polyfill IE 11 end */

        new URL('http://localhost:8080/?a=1&b=3&c=z#123').searchParams.get('c'); // this will return "z"

But if it doesn't work for you, you could take I think full suported and polifilled function from this package here on the url:

https://www.npmjs.com/package/url-polyfill

Here's another polyfill specifically for the URL api, intended to work exactly as it does in modern browsers and only run if needed. This way you don't need to use a separate function that will be obsolete once you decide to drop support for IE.

<script src="https://gist.github.com/ryangoree/def0a520ed43c6c465d9a6518161bc7c.js"></script>

Gist Page : https://gist.github.com/ryangoree/def0a520ed43c6c465d9a6518161bc7c

modified @ales code for getting the value of a particular parameter. The default value is set to false .

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

  if (index) {
    return vars[index] || false;
  }
  return vars;
}

I needed one like this and then un-needed it :). So I'll post it here

var urlRegex = /(.*:)\/\/(.*?)(\/.*?)(\?.*?|#.*?|$)(#.*|$)/

function parseUrl(url) {
  var parts = urlRegex.exec(url)
  var search = parts[4]
  var hash = parts[5]
  if (!search.startsWith('?')) {
    hash = search
    search = ''
  }
  if (!hash.startsWith('#')) {
    hash = ''
  }
  return {
    protocol: parts[1],
    host: parts[2],
    pathname: parts[3],
    search,
    hash,
    searchParams: search
      .replace(/^\?/, '')
      .split('&')
      .reduce((params, kv) => {
          var kvPair = kv.split('=')
          params[kvPair[0]] = kvPair[1]
          return params
        }, {})
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM