2

用途?

用于给url中的特殊字符进行编码。

为什么要用?

因为网络标准RFC1738做了硬性规定,只有字符和数字以及一些规定内的特殊符号,才可以不经过编码用于url,换言之就是,如果你的url中包含了规定之外的符号,那它就是非法的url, 无法被服务器解析,也就无法访问到你想要的网络资源。
为了解决这个问题,js就提供了encodeURIencodeURIComponent来给这些规定之外的符号进行编码,这样,服务器就能正常解析并访问了。

用法?

encodeURI

encodeURI()会编码除去ASCII码、数字和~!@#$&*()=:/,;?+.-_'之外的所有字符。

const url = 'http://www.test.com/images/花朵.png'

const nextUrl = encodeURI(url)
console.log(nextUrl)
// http://www.test.com/images/%E8%8A%B1%E6%9C%B5.png

encodeURIComponent

encodeURIComponent()会编码除去ASCII码、数字和~!*().-_'之外的所有字符。

const url = 'http://www.test.com/images/花朵.png'

const nextUrl = encodeURIComponent(url)
console.log(nextUrl)
//  http%3A%2F%2Fwww.test.com%2Fimages%2F%E8%8A%B1%E6%9C%B5.png

两者之间的差异

encodeURIComponent能够对更多的字符进行编码。

函数安全字符
encodeURI(82个)!#$&'()*+,/:;=?@-._~0-9a-zA-Z
encodeURIComponent(71个)!'()*-._~0-9a-zA-Z

上面的安全字符,就是两个api遇到这些字符不会对其编码。
比如传入=encodeURI,会被原样返回,而传入=encodeURIComponent就会返回%3D,所以encodeURIComponent的编码字符范围更广。

两者之间如何选用

由于两者之间唯一的差异就是能编码的字符范围大小,所以需要根据实际需要编码的字符做抉择。

情况1:

const url = 'http://www.test.com/images/花朵.png'

console.log(encodeURI(url))
http://www.test.com/images/%E8%8A%B1%E6%9C%B5.png

console.log(encodeURIComponent(url))
http%3A%2F%2Fwww.test.com%2Fimages%2F%E8%8A%B1%E6%9C%B5.png

通过上面的示例我们发现,由于encodeURIComponent的编码范围很广,如果对整个URL调用,会导致URL中有特殊作用的符号被编码,变成一个非法的URL了,也就无法访问了。所以此种情况应该选用encodeURI

情况2:

const name = 'AT&T'

console.log(encodeURI(name))
// AT&T

console.log(encodeURIComponent(name))
// AT%26T

由于encodeURI的编码范围较小,导致此处我们希望被编码的&并没有被编码。所以此种情况应该选用encodeURIComponent

应用场景

场景1:使用encodeURIComponent

url参数中包含特殊字符

// 美国电话电报公司
const name = 'AT&T'
const url = `http://www.test.com?name=${name}`

const nextUrl = new URL(url)
const search = new URLSearchParams(nextUrl.search)
console.log(search.get('name'))
// AT

输出的结果缺少了一部分,这是因为&是一个标准的url参数分割符,所以会被解析为分割符。虽然如此,但本例中的&符号是属于名字的一部分,我们不想让它被解析为url的参数分隔符。这时我们就可以使用encodeURIComponentname的值进行编码,这样&就不会被识别为参数分割符了。

// 美国电话电报公司
const name = 'AT&T'
const url = `http://www.test.com?name=${encodeURIComponent(name)}`

const nextUrl = new URL(url)
const search = new URLSearchParams(nextUrl.search)
console.log(search.get('name'))
// AT&T

场景2:使用encodeURIComponent

将一个回调地址作为参数附加在另一个地址上

const redirectUrl = 'http://www.result.com?type=success&num=10'
const targetUrl = `http://www.test.com?redirectUrl=${redirectUrl}`

const url = new URL(targetUrl);
const search = new URLSearchParams(url.search)
console.log(search.get('redirectUrl'))
// http://www.result.com?type=success

我们获取redirectUrl参数时,会发现num参数丢失了,这是因为&被当成www.test.com的参数分隔符了,这里我们可以使用encodeURIComponent来对redirectUrl进行编码就能解决这个问题。

const redirectUrl = 'http://www.result.com?type=success&num=10'
const targetUrl = `http://www.test.com?redirectUrl=${encodeURIComponent(redirectUrl)}`

const url = new URL(targetUrl);
const search = new URLSearchParams(url.search)
console.log(search.get('redirectUrl'))
// http://www.result.com?type=success&num=10

场景3:使用encodeURI

想对整个url调用编码函数,但是又不想误伤url的保留字符,就需要使用encodeURI

const url = "http://www.example.com/?name=小明&age=20"

const nextUrl = encodeURI(url)
console.log(nextUrl)
// http://www.example.com/?name=%E5%B0%8F%E6%98%8E&age=20

疑问

现代浏览器会自动识别URL中的特殊字符并将其编码,那还需要我们手动调用encodeURIencodeURIComponent吗?

答案是看情况,比如在参数中有中文的情况下,中文在URL中不会有歧义(中文在URL中不会有其它含义),所以浏览器会帮你完成编码,但是,在有些情况下,浏览器是不知道你是否需要编码的,我们拿前面的一个示例:

// 美国电话电报公司
const name = 'AT&T'

这里的&URL中有两种含义,一是作为参数分割符,二是作为普通的字符,这时,浏览器确定猜测你的真实意图,也就不会帮你自动编码了,所以需要你主动调用encodeURIComponent

注意事项

  • 他们对特殊字符的编码形式是utf-8

热饭班长
3.7k 声望434 粉丝

先去做,做出一坨狗屎,再改进。