JavaScript Location 對象,URL 對象,URLSearchParams 對象

2023-03-20 15:45 更新

URL 是互聯(lián)網(wǎng)的基礎(chǔ)設(shè)施之一。瀏覽器提供了一些原生對象,用來管理 URL。

Location 對象 

Location對象是瀏覽器提供的原生對象,提供 URL 相關(guān)的信息和操作方法。通過window.locationdocument.location屬性,可以拿到這個(gè)對象。

屬性 

Location對象提供以下屬性。

  • Location.href:整個(gè) URL。
  • Location.protocol:當(dāng)前 URL 的協(xié)議,包括冒號(:)。
  • Location.host:主機(jī)。如果端口不是協(xié)議默認(rèn)的80433,則還會包括冒號(:)和端口。
  • Location.hostname:主機(jī)名,不包括端口。
  • Location.port:端口號。
  • Location.pathname:URL 的路徑部分,從根路徑/開始。
  • Location.search:查詢字符串部分,從問號?開始。
  • Location.hash:片段字符串部分,從#開始。
  • Location.username:域名前面的用戶名。
  • Location.password:域名前面的密碼。
  • Location.origin:URL 的協(xié)議、主機(jī)名和端口。
// 當(dāng)前網(wǎng)址為
// http://user:passwd@www.example.com:4097/path/a.html?x=111#part1
document.location.href
// "http://user:passwd@www.example.com:4097/path/a.html?x=111#part1"
document.location.protocol
// "http:"
document.location.host
// "www.example.com:4097"
document.location.hostname
// "www.example.com"
document.location.port
// "4097"
document.location.pathname
// "/path/a.html"
document.location.search
// "?x=111"
document.location.hash
// "#part1"
document.location.username
// "user"
document.location.password
// "passwd"
document.location.origin
// "http://user:passwd@www.example.com:4097"

這些屬性里面,只有origin屬性是只讀的,其他屬性都可寫。

注意,如果對Location.href寫入新的 URL 地址,瀏覽器會立刻跳轉(zhuǎn)到這個(gè)新地址。

// 跳轉(zhuǎn)到新網(wǎng)址
document.location.;

這個(gè)特性常常用于讓網(wǎng)頁自動滾動到新的錨點(diǎn)。

document.location.href = '#top';
// 等同于
document.location.hash = '#top';

直接改寫location,相當(dāng)于寫入href屬性。

document.location = 'http://www.example.com';
// 等同于
document.location.;

另外,Location.href屬性是瀏覽器唯一允許跨域?qū)懭氲膶傩裕捶峭吹拇翱诳梢愿膶懥硪粋€(gè)窗口(比如子窗口與父窗口)的Location.href屬性,導(dǎo)致后者的網(wǎng)址跳轉(zhuǎn)。Location的其他屬性都不允許跨域?qū)懭搿?/p>

方法 

(1)Location.assign()

assign方法接受一個(gè) URL 字符串作為參數(shù),使得瀏覽器立刻跳轉(zhuǎn)到新的 URL。如果參數(shù)不是有效的 URL 字符串,則會報(bào)錯(cuò)。

// 跳轉(zhuǎn)到新的網(wǎng)址
document.location.assign('http://www.example.com')

(2)Location.replace()

replace方法接受一個(gè) URL 字符串作為參數(shù),使得瀏覽器立刻跳轉(zhuǎn)到新的 URL。如果參數(shù)不是有效的 URL 字符串,則會報(bào)錯(cuò)。

它與assign方法的差異在于,replace會在瀏覽器的瀏覽歷史History里面刪除當(dāng)前網(wǎng)址,也就是說,一旦使用了該方法,后退按鈕就無法回到當(dāng)前網(wǎng)頁了,相當(dāng)于在瀏覽歷史里面,使用新的 URL 替換了老的 URL。它的一個(gè)應(yīng)用是,當(dāng)腳本發(fā)現(xiàn)當(dāng)前是移動設(shè)備時(shí),就立刻跳轉(zhuǎn)到移動版網(wǎng)頁。

// 跳轉(zhuǎn)到新的網(wǎng)址
document.location.replace('http://www.example.com')

(3)Location.reload()

reload方法使得瀏覽器重新加載當(dāng)前網(wǎng)址,相當(dāng)于按下瀏覽器的刷新按鈕。

它接受一個(gè)布爾值作為參數(shù)。如果參數(shù)為true,瀏覽器將向服務(wù)器重新請求這個(gè)網(wǎng)頁,并且重新加載后,網(wǎng)頁將滾動到頭部(即scrollTop === 0)。如果參數(shù)是false或?yàn)榭?,瀏覽器將從本地緩存重新加載該網(wǎng)頁,并且重新加載后,網(wǎng)頁的視口位置是重新加載前的位置。

// 向服務(wù)器重新請求當(dāng)前網(wǎng)址
window.location.reload(true);

(4)Location.toString()

toString方法返回整個(gè) URL 字符串,相當(dāng)于讀取Location.href屬性。

URL 的編碼和解碼 

網(wǎng)頁的 URL 只能包含合法的字符。合法字符分成兩類。

  • URL 元字符:分號(;),逗號(,),斜杠(/),問號(?),冒號(:),at(@),&,等號(=),加號(+),美元符號($),井號(#
  • 語義字符:a-z,A-Z,0-9,連詞號(-),下劃線(_),點(diǎn)(.),感嘆號(!),波浪線(~),星號(*),單引號('),圓括號(()

除了以上字符,其他字符出現(xiàn)在 URL 之中都必須轉(zhuǎn)義,規(guī)則是根據(jù)操作系統(tǒng)的默認(rèn)編碼,將每個(gè)字節(jié)轉(zhuǎn)為百分號(%)加上兩個(gè)大寫的十六進(jìn)制字母。

比如,UTF-8 的操作系統(tǒng)上,http://www.example.com/q=春節(jié)這個(gè) URL 之中,漢字“春節(jié)”不是 URL 的合法字符,所以被瀏覽器自動轉(zhuǎn)成http://www.example.com/q=%E6%98%A5%E8%8A%82。其中,“春”轉(zhuǎn)成了%E6%98%A5,“節(jié)”轉(zhuǎn)成了%E8%8A%82。這是因?yàn)椤按骸焙汀肮?jié)”的 UTF-8 編碼分別是E6 98 A5E8 8A 82,將每個(gè)字節(jié)前面加上百分號,就構(gòu)成了 URL 編碼。

JavaScript 提供四個(gè) URL 的編碼/解碼方法。

  • encodeURI()
  • encodeURIComponent()
  • decodeURI()
  • decodeURIComponent()

encodeURI() 

encodeURI()方法用于轉(zhuǎn)碼整個(gè) URL。它的參數(shù)是一個(gè)字符串,代表整個(gè) URL。它會將元字符和語義字符之外的字符,都進(jìn)行轉(zhuǎn)義。

encodeURI('http://www.example.com/q=春節(jié)')
// "http://www.example.com/q=%E6%98%A5%E8%8A%82"

encodeURIComponent() 

encodeURIComponent()方法用于轉(zhuǎn)碼 URL 的組成部分,會轉(zhuǎn)碼除了語義字符之外的所有字符,即元字符也會被轉(zhuǎn)碼。所以,它不能用于轉(zhuǎn)碼整個(gè) URL。它接受一個(gè)參數(shù),就是 URL 的片段。

encodeURIComponent('春節(jié)')
// "%E6%98%A5%E8%8A%82"
encodeURIComponent('http://www.example.com/q=春節(jié)')
// "http%3A%2F%2Fwww.example.com%2Fq%3D%E6%98%A5%E8%8A%82"

上面代碼中,encodeURIComponent()會連 URL 元字符一起轉(zhuǎn)義,所以如果轉(zhuǎn)碼整個(gè) URL 就會出錯(cuò)。

decodeURI() 

decodeURI()方法用于整個(gè) URL 的解碼。它是encodeURI()方法的逆運(yùn)算。它接受一個(gè)參數(shù),就是轉(zhuǎn)碼后的 URL。

decodeURI('http://www.example.com/q=%E6%98%A5%E8%8A%82')
// "http://www.example.com/q=春節(jié)"

decodeURIComponent() 

decodeURIComponent()用于URL 片段的解碼。它是encodeURIComponent()方法的逆運(yùn)算。它接受一個(gè)參數(shù),就是轉(zhuǎn)碼后的 URL 片段。

decodeURIComponent('%E6%98%A5%E8%8A%82')
// "春節(jié)"

URL 接口 

瀏覽器原生提供URL()接口,它是一個(gè)構(gòu)造函數(shù),用來構(gòu)造、解析和編碼 URL。一般情況下,通過window.URL可以拿到這個(gè)構(gòu)造函數(shù)。

構(gòu)造函數(shù) 

URL()作為構(gòu)造函數(shù),可以生成 URL 實(shí)例。它接受一個(gè)表示 URL 的字符串作為參數(shù)。如果參數(shù)不是合法的 URL,會報(bào)錯(cuò)。

var url = new URL('http://www.example.com/index.html');
url.href
// "http://www.example.com/index.html"

上面示例生成了一個(gè) URL 實(shí)例,用來代表指定的網(wǎng)址。

除了字符串,URL()的參數(shù)也可以是另一個(gè) URL 實(shí)例。這時(shí),URL()會自動讀取該實(shí)例的href屬性,作為實(shí)際參數(shù)。

如果 URL 字符串是一個(gè)相對路徑,那么需要表示絕對路徑的第二個(gè)參數(shù),作為計(jì)算基準(zhǔn)。

var url1 = new URL('index.html', 'http://example.com');
url1.href
// "http://example.com/index.html"

var url2 = new URL('page2.html', 'http://example.com/page1.html');
url2.href
// "http://example.com/page2.html"

var url3 = new URL('..', 'http://example.com/a/b.html')
url3.href
// "http://example.com/"

上面代碼中,返回的 URL 實(shí)例的路徑都是在第二個(gè)參數(shù)的基礎(chǔ)上,切換到第一個(gè)參數(shù)得到的。最后一個(gè)例子里面,第一個(gè)參數(shù)是..,表示上層路徑。

實(shí)例屬性 

URL 實(shí)例的屬性與Location對象的屬性基本一致,返回當(dāng)前 URL 的信息。

  • URL.href:返回整個(gè) URL
  • URL.protocol:返回協(xié)議,以冒號:結(jié)尾
  • URL.hostname:返回域名
  • URL.host:返回域名與端口,包含:號,默認(rèn)的80和443端口會省略
  • URL.port:返回端口
  • URL.origin:返回協(xié)議、域名和端口
  • URL.pathname:返回路徑,以斜杠/開頭
  • URL.search:返回查詢字符串,以問號?開頭
  • URL.searchParams:返回一個(gè)URLSearchParams實(shí)例,該屬性是Location對象沒有的
  • URL.hash:返回片段識別符,以井號#開頭
  • URL.password:返回域名前面的密碼
  • URL.username:返回域名前面的用戶名
var url = new URL('http://user:passwd@www.example.com:4097/path/a.html?x=111#part1');

url.href
// "http://user:passwd@www.example.com:4097/path/a.html?x=111#part1"
url.protocol
// "http:"
url.hostname
// "www.example.com"
url.host
// "www.example.com:4097"
url.port
// "4097"
url.origin
// "http://www.example.com:4097"
url.pathname
// "/path/a.html"
url.search
// "?x=111"
url.searchParams
// URLSearchParams {}
url.hash
// "#part1"
url.password
// "passwd"
url.username
// "user"

這些屬性里面,只有origin屬性是只讀的,其他屬性都可寫,并且會立即生效。

var url = new URL('http://example.com/index.html#part1');

url.pathname = 'index2.html';
url.href // "http://example.com/index2.html#part1"

url.hash = '#part2';
url.href // "http://example.com/index2.html#part2"

上面代碼中,改變 URL 實(shí)例的pathname屬性和hash屬性,都會實(shí)時(shí)反映在 URL 實(shí)例當(dāng)中。

靜態(tài)方法 

(1)URL.createObjectURL()

URL.createObjectURL()方法用來為上傳/下載的文件、流媒體文件生成一個(gè) URL 字符串。這個(gè)字符串代表了File對象或Blob對象的 URL。

// HTML 代碼如下
// <div id="display"/>
// <input
//   type="file"
//   id="fileElem"
//   multiple
//   accept="image/*"
//   onchange="handleFiles(this.files)"
//  >
var div = document.getElementById('display');

function handleFiles(files) {
  for (var i = 0; i < files.length; i++) {
    var img = document.createElement('img');
    img.src = window.URL.createObjectURL(files[i]);
    div.appendChild(img);
  }
}

上面代碼中,URL.createObjectURL()方法用來為上傳的文件生成一個(gè) URL 字符串,作為<img>元素的圖片來源。

該方法生成的 URL 就像下面的樣子。

blob:http://localhost/c745ef73-ece9-46da-8f66-ebes574789b1

注意,每次使用URL.createObjectURL()方法,都會在內(nèi)存里面生成一個(gè) URL 實(shí)例。如果不再需要該方法生成的 URL 字符串,為了節(jié)省內(nèi)存,可以使用URL.revokeObjectURL()方法釋放這個(gè)實(shí)例。

(2)URL.revokeObjectURL()

URL.revokeObjectURL()方法用來釋放URL.createObjectURL()方法生成的 URL 實(shí)例。它的參數(shù)就是URL.createObjectURL()方法返回的 URL 字符串。

下面為上一段的示例加上URL.revokeObjectURL()。

var div = document.getElementById('display');

function handleFiles(files) {
  for (var i = 0; i < files.length; i++) {
    var img = document.createElement('img');
    img.src = window.URL.createObjectURL(files[i]);
    div.appendChild(img);
    img.onload = function() {
      window.URL.revokeObjectURL(this.src);
    }
  }
}

上面代碼中,一旦圖片加載成功以后,為本地文件生成的 URL 字符串就沒用了,于是可以在img.onload回調(diào)函數(shù)里面,通過URL.revokeObjectURL()方法卸載這個(gè) URL 實(shí)例。

URLSearchParams 對象 

概述 

URLSearchParams對象是瀏覽器的原生對象,用來構(gòu)造、解析和處理 URL 的查詢字符串(即 URL 問號后面的部分)。

它本身也是一個(gè)構(gòu)造函數(shù),可以生成實(shí)例。參數(shù)可以為查詢字符串,起首的問號?有沒有都行,也可以是對應(yīng)查詢字符串的數(shù)組或?qū)ο蟆?/p>

// 方法一:傳入字符串
var params = new URLSearchParams('?foo=1&bar=2');
// 等同于
var params = new URLSearchParams(document.location.search);

// 方法二:傳入數(shù)組
var params = new URLSearchParams([['foo', 1], ['bar', 2]]);

// 方法三:傳入對象
var params = new URLSearchParams({'foo' : 1 , 'bar' : 2});

URLSearchParams會對查詢字符串自動編碼。

var params = new URLSearchParams({'foo': '你好'});
params.toString() // "foo=%E4%BD%A0%E5%A5%BD"

上面代碼中,foo的值是漢字,URLSearchParams對其自動進(jìn)行 URL 編碼。

瀏覽器向服務(wù)器發(fā)送表單數(shù)據(jù)時(shí),可以直接使用URLSearchParams實(shí)例作為表單數(shù)據(jù)。

const params = new URLSearchParams({foo: 1, bar: 2});
fetch('https://example.com/api', {
  method: 'POST',
  body: params
}).then(...)

上面代碼中,fetch命令向服務(wù)器發(fā)送命令時(shí),可以直接使用URLSearchParams實(shí)例。

URLSearchParams可以與URL()接口結(jié)合使用。

var url = new URL(window.location);
var foo = url.searchParams.get('foo') || 'somedefault';

上面代碼中,URL 實(shí)例的searchParams屬性就是一個(gè)URLSearchParams實(shí)例,所以可以使用URLSearchParams接口的get方法。

URLSearchParams實(shí)例有遍歷器接口,可以用for...of循環(huán)遍歷(詳見《ES6 標(biāo)準(zhǔn)入門》的《Iterator》一章)。

var params = new URLSearchParams({'foo': 1 , 'bar': 2});

for (var p of params) {
  console.log(p[0] + ': ' + p[1]);
}
// foo: 1
// bar: 2

URLSearchParams沒有實(shí)例屬性,只有實(shí)例方法。

URLSearchParams.toString() 

toString方法返回實(shí)例的字符串形式。

var url = new URL('https://example.com?foo=1&bar=2');
var params = new URLSearchParams(url.search);

params.toString() // "foo=1&bar=2'

那么需要字符串的場合,會自動調(diào)用toString方法。

var params = new URLSearchParams({version: 2.0});
window.location.href = location.pathname + '?' + params;

上面代碼中,location.href賦值時(shí),可以直接使用params對象。這時(shí)就會自動調(diào)用toString方法。

URLSearchParams.append() 

append()方法用來追加一個(gè)查詢參數(shù)。它接受兩個(gè)參數(shù),第一個(gè)為鍵名,第二個(gè)為鍵值,沒有返回值。

var params = new URLSearchParams({'foo': 1 , 'bar': 2});
params.append('baz', 3);
params.toString() // "foo=1&bar=2&baz=3"

append()方法不會識別是否鍵名已經(jīng)存在。

var params = new URLSearchParams({'foo': 1 , 'bar': 2});
params.append('foo', 3);
params.toString() // "foo=1&bar=2&foo=3"

上面代碼中,查詢字符串里面foo已經(jīng)存在了,但是append依然會追加一個(gè)同名鍵。

URLSearchParams.delete() 

delete()方法用來刪除指定的查詢參數(shù)。它接受鍵名作為參數(shù)。

var params = new URLSearchParams({'foo': 1 , 'bar': 2});
params.delete('bar');
params.toString() // "foo=1"

URLSearchParams.has() 

has()方法返回一個(gè)布爾值,表示查詢字符串是否包含指定的鍵名。

var params = new URLSearchParams({'foo': 1 , 'bar': 2});
params.has('bar') // true
params.has('baz') // false

URLSearchParams.set() 

set()方法用來設(shè)置查詢字符串的鍵值。

它接受兩個(gè)參數(shù),第一個(gè)是鍵名,第二個(gè)是鍵值。如果是已經(jīng)存在的鍵,鍵值會被改寫,否則會被追加。

var params = new URLSearchParams('?foo=1');
params.set('foo', 2);
params.toString() // "foo=2"
params.set('bar', 3);
params.toString() // "foo=2&bar=3"

上面代碼中,foo是已經(jīng)存在的鍵,bar是還不存在的鍵。

如果有多個(gè)的同名鍵,set會移除現(xiàn)存所有的鍵。

var params = new URLSearchParams('?foo=1&foo=2');
params.set('foo', 3);
params.toString() // "foo=3"

下面是一個(gè)替換當(dāng)前 URL 的例子。

// URL: https://example.com?version=1.0
var params = new URLSearchParams(location.search.slice(1));
params.set('version', '2.0');

window.history.replaceState({}, '', location.pathname + `?` + params);
// URL: https://example.com?version=2.0

URLSearchParams.get(),URLSearchParams.getAll() 

get()方法用來讀取查詢字符串里面的指定鍵。它接受鍵名作為參數(shù)。

var params = new URLSearchParams('?foo=1');
params.get('foo') // "1"
params.get('bar') // null

兩個(gè)地方需要注意。第一,它返回的是字符串,如果原始值是數(shù)值,需要轉(zhuǎn)一下類型;第二,如果指定的鍵名不存在,返回值是null。

如果有多個(gè)的同名鍵,get返回位置最前面的那個(gè)鍵值。

var params = new URLSearchParams('?foo=3&foo=2&foo=1');
params.get('foo') // "3"

上面代碼中,查詢字符串有三個(gè)foo鍵,get方法返回最前面的鍵值3。

getAll()方法返回一個(gè)數(shù)組,成員是指定鍵的所有鍵值。它接受鍵名作為參數(shù)。

var params = new URLSearchParams('?foo=1&foo=2');
params.getAll('foo') // ["1", "2"]

上面代碼中,查詢字符串有兩個(gè)foo鍵,getAll返回的數(shù)組就有兩個(gè)成員。

URLSearchParams.sort() 

sort()方法對查詢字符串里面的鍵進(jìn)行排序,規(guī)則是按照 Unicode 碼點(diǎn)從小到大排列。

該方法沒有返回值,或者說返回值是undefined

var params = new URLSearchParams('c=4&a=2&b=3&a=1');
params.sort();
params.toString() // "a=2&a=1&b=3&c=4"

上面代碼中,如果有兩個(gè)同名的鍵a,它們之間不會排序,而是保留原始的順序。

URLSearchParams.keys(),URLSearchParams.values(),URLSearchParams.entries() 

這三個(gè)方法都返回一個(gè)遍歷器對象,供for...of循環(huán)遍歷。它們的區(qū)別在于,keys方法返回的是鍵名的遍歷器,values方法返回的是鍵值的遍歷器,entries返回的是鍵值對的遍歷器。

var params = new URLSearchParams('a=1&b=2');

for(var p of params.keys()) {
  console.log(p);
}
// a
// b

for(var p of params.values()) {
  console.log(p);
}
// 1
// 2

for(var p of params.entries()) {
  console.log(p);
}
// ["a", "1"]
// ["b", "2"]

如果直接對URLSearchParams進(jìn)行遍歷,其實(shí)內(nèi)部調(diào)用的就是entries接口。

for (var p of params) {}
// 等同于
for (var p of params.entries()) {}

參考鏈接 


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號