いまさら~だけど、改めて調べたら知らないこともあった。

  1. 現在のURLをゴミ無しで取得
  2. 任意のURLを分解して取得
  3. URLからいろんなものを全部取得
  4. クエリストリングをオブジェクトで取得
  5. ウェルノウンポートは取得できない?

現在のURLをゴミ無しで取得

とりあえずクエリストリング (?) やフラグメント識別子 (#) 無しで取得したかったら↓こう。

var url = `${location.protocol}//${location.host}${location.pathname}`;
console.log(url);
// -> https://note.kiriukun.com/entry/20190209-get-current-url-in-javascript

任意のURLを分解して取得

window.location は現在のURLでしか使えない。好きなURLを分解する方法。

URLオブジェクトを使う

var url = new URL('http://note.kiriukun.com/aaaaa/wwwww');

console.log( url.href );      // -> http://note.kiriukun.com/aaaaa/wwwww
console.log( url.protocol );  // -> http:
console.log( url.host );      // -> note.kiriukun.com
console.log( url.pathname );  // -> /aaaaa/wwwww
console.log( url.origin );    // -> http://note.kiriukun.com

a要素を使う

MDNの Location のページのサンプルで見かけました。

var url = document.createElement('a');
url.href = 'http://note.kiriukun.com/aaaaa/wwwww';

console.log( url.href );      // -> http://note.kiriukun.com/aaaaa/wwwww
console.log( url.protocol );  // -> http:
console.log( url.host );      // -> note.kiriukun.com
console.log( url.pathname );  // -> /aaaaa/wwwww
console.log( url.origin );    // -> http://note.kiriukun.com

URLからいろんなものを全部取得

全部詰め込んだやつだと↓こう。

var url = new URL('http://hoge:piyo@note.kiriukun.com:8080/aaaaa/wwwww?v=123#here');

console.log( url.href );      // -> http://hoge:piyo@note.kiriukun.com:8080/aaaaa/wwwww?v=123#here
console.log( url.protocol );  // -> http:
console.log( url.username );  // -> hoge
console.log( url.password );  // -> piyo
console.log( url.host );      // -> note.kiriukun.com:8080
console.log( url.hostname );  // -> note.kiriukun.com
console.log( url.port );      // -> 8080
console.log( url.pathname );  // -> /aaaaa/wwwww
console.log( url.search );    // -> ?v=123
console.log( url.hash );      // -> #here
console.log( url.origin );    // -> http://note.kiriukun.com:8080

普通にブラウザから使ってたら無いと思うけど、ユーザーとパスワードが入ってたら location.usernamelocation.password で取れる。

クエリストリングをオブジェクトで取得

URL.searchParams というのもあるが、対応してるブラウザが少ない。

自力でパースするなら↓こう。

function getSearchParams() {
	var params = {};
	var search = window.location.search.substr(1);
	if (search === '') {
		return params;
	}
	search.split('&').forEach(str => {
		var arr = str.split('=');
		if (arr[0] !== '') {
			params[arr[0]] = arr[1] !== undefined ? decodeURIComponent(arr[1]) : '';
		}
	});
	return params;
}

// URL末尾に ?a=%E3%81%82%E3%81%82%E3%81%82&b=&c&d=0&e=1&f=aaa がついてる場合
console.log(getSearchParams());
/* -> {
	a: "あああ"
	b: ""
	c: ""
	d: "0"
	e: "1"
	f: "aaa"
} */

Dropbox API v2でしか見たことないが、フラグメント識別子 (URLの#以降) に同じようなパラメータが入ってる場合でも、上記の関数の window.location.searchwindow.location.hash に変更すれば同様に取得できる。

ウェルノウンポートは取得できない?

これ書いてて気づいたんだけど、少なくともHTTP/HTTPS/FTPだと、ポート番号にウェルノウンポートが明示的に指定されてても取得できないっぽい。

以下はChrome (71.0.3578.98) で試した時の結果。どれもポート番号を変えると普通に取得できるんだけど。

HTTPでポート80番
var url = new URL('http://note.kiriukun.com:80');

console.log( url.href );      // -> http://note.kiriukun.com/
console.log( url.protocol );  // -> http:
console.log( url.host );      // -> note.kiriukun.com
console.log( url.port );      // -> 
console.log( url.origin );    // -> http://note.kiriukun.com
HTTPでポート443番
var url = new URL('https://note.kiriukun.com:443');

console.log( url.href );      // -> https://note.kiriukun.com/
console.log( url.protocol );  // -> https:
console.log( url.host );      // -> note.kiriukun.com
console.log( url.port );      // -> 
console.log( url.origin );    // -> https://note.kiriukun.com
FTPでポート21番
var url = new URL('ftp://note.kiriukun.com:211');

console.log( url.href );      // -> ftp://note.kiriukun.com/
console.log( url.protocol );  // -> ftp:
console.log( url.host );      // -> note.kiriukun.com
console.log( url.port );      // -> 
console.log( url.origin );    // -> ftp://note.kiriukun.com

HTTPとHTTPSに限っては、Edge (42.17134.1.0) のコンソールで同じコードを動かすと、3行目で「SCRIPT14: セキュリティの問題が発生しました。」というエラーが出てそもそも分解できなかった。

他のプロトコルはまだ試せてない。