1. document
    1. document.URL
    2. document.documentURI
    3. node.baseURI
    4. URL documentURI baseURI location.href 的区别
    5. document.domain
  2. window.location
    1. location.href
    2. location.origin
    3. location.protocol
    4. location.host
    5. location.hostname
    6. location.port
    7. location.pathname
    8. location.hash
    9. location.search
    10. location.assign()
    11. location.replace()
    12. location.reload()
    13. location.ancestorOrigins
  3. URL 的结构
  4. 参考

URL

document

document.URL

返回当前文档的 URL 地址,只读.
只能在 HTML 文档中使用.

Document.URL - Web APIs | MDN

document.documentURI

返回当前文档的 URL 地址,只读.
在 DOM3 规范中定义为可写, DOM4 改为只读.
没有文档类型限制,可用于任何文档.

IE 不支持此属性

Document.documentURI - Web APIs | MDN

node.baseURI

返回当前元素所在文档的 URL 地址,只读.
可用于任何 Dom 元素.

1
document.querySelector("div").baseURI; // http://127.0.0.1/index.html

该属性通常等于 document.location.href,受 <base> 元素影响.

1
2
3
4
5
<base href="htttp://example.com" />
<script>
console.log(document.location.href); // http://127.0.0.1/index.html
console.log(document.baseURI); // htttp://example.com
</script>

IE 不支持此属性

Node.baseURI - Web APIs | MDN

URL documentURI baseURI location.href 的区别

通常以下四者的返回值相同,都返回字符串格式的文档地址:

  • document.URL
  • document.documentURI
  • window.location.href
  • node.baseURI

四者的区别如下:

1 只有 document 拥有 URL/location/documentURI 属性,而 baseURI 可用于任何 Dom 元素.

2 URL documentURI baseURI 三者为只读属性, 不能修改.而 location.href 可以被修改.

3 node.baseURI 受 base 元素的 href 值影响, 而另外三者不受影响.

4 关于 document.URL 和 document.documentURI 的区别.
很多文档都提到 URL 只能用于 HTML 文档, 而 document.documentURI 可用于任意文档.
但没有找到任何可正常运行的相关示例.例如下面这个例子,在 chrome 中无论是 URL 还是 documentURI 都能正常工作.
html - Some cases when document.documentURI is available but not document.URL - Stack Overflow

5 document.URL 属于比较老的 api, 作为代替应该尽量使用 window.location.href 而非 document.URL.

document.domain

获取/设置当前文档 URL 的 domain 部分.
通常情况下等于 document.location.hostname. ? 更改 document.domain 值不会更新文档的 URL.

设置 document.domain 时有规则限制.
可以更改子域的 domain 值为父域, 但不能更改父域的 domain 值为子域.

修改子域为父域,成功.

1
2
document.domain; // "sub.test.t"
document.domain = "test.t"; // test.t

修改父域为子域, 报错.

1
2
3
document.domain; // "test.t"
document.domain = "sub.test.t";
// DOMException: Failed to set the 'domain' property on 'Document': 'sub.test.t' is not a suffix of 'test.t'.

也不能修改 domain 的顶级域名.

1
2
3
4
5
6
7
document.domain; // "test.t"

document.domain = "test.org";
// OMException: Failed to set the 'domain' property on 'Document': 'test.org' is not a suffix of 'test.t'.

document.domain = "org";
// OMException: Failed to set the 'domain' property on 'Document': 'org' is not a suffix of 'test.t'.

document.domain 可用于绕过同源策略, 解除跨域操作 iframe 的限制.
如下是在 test.t/index.html 中获取 iframe(sub.test.t/foo.html) 内 window.foo 属性的例子:

test.t/index.html 的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<iframe src="http://sub.test.t:5500/foo.html" frameborder="0"></iframe>
<script>
console.log(document.domain); // "test.t"
// 注意: 两边都需要手动设置 domain 为相同的值, 否则会报错 DOMException: Blocked a frame with origin.
// 即便 当前的 domain 默认值就是 "test.t"
document.domain = "test.t";
// 注意: 该 script 会先于 iframe 中的 script 执行
// 因此把后续操作放在 onload 事件里, 等待 iframe 加载后在执行下面的 js 代码
// 否则 console.log(iframeWin.foo); 的输出值会是 undefined
window.onload = function() {
const iframeEl = document.querySelector("iframe");
const iframeWin = iframeEl.contentWindow;
console.log(iframeWin.foo); // bar
};
</script>

sub.test.t/foo.html 的代码:

1
2
3
4
5
6
7
<body>
foo page
<script>
document.domain = "test.t";
window.foo = "bar";
</script>
</body>

window.location

返回 Location 对象, 包含当前文档的 URL 信息.
可以通过操作 Location 来跳转到目标的 URL.

除了 window.location 之外, 还有一个类似的属性 document.location,二者都返回相同的对象.
现代的大部分浏览器都将 document.location 指向 window.location.

1
document.location === location; // true

推荐使用 window.location, document.location 的存在属于历史遗留问题.
What's the difference between window.location and document.location in JavaScript? - Stack Overflow

location.href

读取/设置当前文档的 URL

1
2
3
window.location.href = "http://example.com";
// or
window.location = "http://example.com";

location.origin

返回 Location 对象的 URL origin, 只读.

1
location.origin; // "http://test.t:5500"

location.protocol

读取/设置 Location 对象的 URL protocol.

1
location.protocol; // "http:"

location.host

读取/设置 Location 对象的 URL hostname 和 port

1
location.host // "test.t:8000"

location.hostname

读取/设置 Location 对象的 主机名称

1
location.hostname // "test.t:8000"

location.port

读取/设置 Location 对象的端口,如果未显示设置端口号.

1
location.port // "test.t:8000"

location.pathname

读取/设置 Location 对象的 URL 路径

1
location.pathname // "/index.html"

location.hash

获取/设置文档 URL 的 fragment identifier(片段标识符,由 # 号开头的一组字符)

1
2
document.location.href; // "http://test.t/index.html#foo"
document.location.hash; // "#foo"

Fragment_identifier

location.search

获取/设置文档 URL 的 query string (查询字符串,由 ? 号开头的一组字符)

Query_string

1
2
location.href; // "http://test.t/index.html?foo=bar"
location.search; // "?foo=bar"

如果不需要支持 IE, 可以通过 URLSearchParams 来解析 query string.

URLSearchParams

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
console.log(location.href); // "http://test.t/index.html?a=1"
const params = new URLSearchParams(location.search);
// 获取
params.get("a"); // "1"

// 新增
// URLSearchParams 不同于 Object, 其允许用 append 添加多个相同的 key
params.append("b", 2);
params.append("b", 3);

// 转字符串, 可用于 URL
// console.log(params.toString()) // a=1&b=2&b=3

// 获取所有相同 key 的值
params.getAll("b"); // ["2", "3"]
params.get("b"); // "2"

// 修改
// 使用 set 修改键值, 如果不存在对应的键, 则会新增一个对应的键值.
params.set("c", 3);
params.getAll("c"); // ["3"]

// 判断是否存在对应的 key
params.has("c"); // true

// 删除
params.delete("b");
params.toString(); // "a=1&c=3"

// 获取所有的键值对, 返回一个 iterator
const entries = params.entries();
for (let [key, value] of entries) {
console.log(key, value); // a 1 c 3
}

// 获取所有的 key, 返回一个 iterator
const keys = params.keys();
for (let key of keys) {
console.log(key); // a c
}

// 获取所有的 value, 返回一个 iterator
const values = params.values();
for (let value of values) {
console.log(value); // 1 3
}
// 排序
params.append("e", 5);
params.append("d", 4);
console.log(params.toString()); // a=1&c=3&e=5&d=4
// 按 key 排序
params.sort(); // a=1&c=3&d=4&e=5

如果需要兼容 IE, 可参考: url - How can I get query string values in JavaScript? - Stack Overflow

location.assign()

跳转到对应的 URL

1
location.assign("https://example.com");

location.replace()

从历史记录中删除当前页, 并跳转到对应的 URL

1
location.assign("https://example.com");

location.reload()

重新加载当前的 URL

1
location.reload();

部分浏览器( 如 firefox) 可传入一个布尔值来控制是否从使用浏览器缓存. 为 true 时不使用浏览器缓存, 强制从服务器获取数据.

1
2
// 不使用浏览器缓存
location.reload(true);

不过这个参数在 chrome 上似乎是无效的.HTML5 规范文档没有提及.

该参数在 chromium 中失效的讨论:
window.location.reload(true) reloads from cache

location.ancestorOrigins

返回一个 DOMStringList 对象, 包含了从 parent browsing context (父浏览器上下文)一直到 top-level browsing context (最顶层的浏览器上下文)的 origin.
如果当前的上下文就是 top-level browsing context, 则返回一个空的 DOMStringList.

下面是一个三层结构的示例, 在 index.html 用 iframe 加载 foo.html. 再在 foo.html 中 用 iframe 加载 bar.html.
最后在 bar.html 中调用 location.ancestorOrigins.

test.t/index.html 的代码:

1
<iframe src="http://sub.test.t/foo.html" frameborder="0"></iframe>

sub.test.t/foo.html 的代码:

1
<iframe src="http://bar.sub.test.t/bar.html" frameborder="0"></iframe>

bar.sub.test.t/bar.html 的代码:

1
2
3
<script>
console.log(location.ancestorOrigins); // {0: "http://sub.test.t", 1: "http://test.t"}
</script>

URL 的结构

捕获.PNG

参考

HTML Standard