文章转自csdn[weixin_39918248] # 如何判断字符串已经被url编码_前端面试题(三) 如何解码一个被编码了不知道多少次的url地址...
防止以后链接失效,将文章copy下来,向原创作者【畅哥聊技术】致敬
话不多说上代码:
var url = 'https://www.baidu.com?a=xxx&b=12&c=水电费、#的'
console.log('编码前',url)
var url2 =encodeURIComponent(url)
console.log('编码1',url2)
url2 =encodeURIComponent(url2)
console.log('编码2',url2)
url2 =encodeURIComponent(url2)
console.log('编码3',url2)
console.log('解码前:',url2)
let url3 = decodeURIComponent(url2)
console.log('解码1后:',url3)
url3 = decodeURIComponent(url3)
console.log('解码2后:',url3)
url3 = decodeURIComponent(url3)
console.log('解码3后:',url3)
/**
* 解码URl 解码一个被编码N次的url
* @param url
* @returns
*/
export const decoeUrl = (uri) => {
if(decodeURIComponent(uri)===uri){
return uri
}else{
return arguments.callee(decodeURIComponent(uri))
}
}
原文内容
如何判断字符串已经被url编码_前端面试题(三) 如何解码一个被编码了不知道多少次的url地址...
1.url编码和解码
这里面有一个坑,我掉进去了,我先说通过encodeURI来编码,decodeURI来解码。我话音刚落,面试官断了我说:你确定吗?
突然的打断让我有些不知所措,导致接下来的面试都不顺利。
我的大脑高速旋转,然后我想到了之前做微信分享的时候,我们传入url的时候需要将地址进行编码,那个好像用不是这个encodeURI,没错,是 encodeURIComponent 这个API,虽然我没有完整的将这个单词说出来,然后我结合业务场景,说出了url编码的一个应用,也算是勉强过关了吧。
说完了以后,面试官说:encodeURI和decodeURI已经不再建议使用了。转而我们应该使用encodeURIComponent 和 dncodeURIComponent来替代。
这个应该只是前戏了,关键是这个题目的本身该如何去解?
不着急解题,我们先来看看这两个api的基本用法。
编码后,程序会将我们的url中的特殊字符进行编码,生成一个新的url,如果继续编码,将会继续生成一个不同的url。
同理,我们再来看下解码过程。
我们将之前编码后的url进行两次解码,可以得到我们最终熟悉的url了。
好了,我们再来回到问题本身。如何解码一个被多次编码的url.也就是说,这个url我们是不知道它被编码了多少次的。
那这个问题该怎么解呢?
第一次面临这样的问题,在面试的过程中可能一下子被问住了。没关系,我们先来看另一个问题。
说:如果遍历一个文件夹中的文件夹和文件。相信这个问题很直白了。文件夹里面可能还有文件夹,里面可以无限嵌套。
其实稍微有些工作经验的就知道,文件夹的问题肯定是要用到递归来处理了。
好,我们再来类比一下我们的今天的这个问题。两个问题有什么相同的地方没有?
解题思路
不难发现,两个问题中,有一个共同的特点。那就是都有一个不确定的因素。不知道文件夹有多少层,不知道url被编码了多少次。
从类比结果我们可以知道,这个url编码的问题应该是要用到递归算法去处理了。
递归算法
关系递归算法的相关知识点,我前面的文章函数那点事已经有了详细的介绍,这里不再赘述了。 首先,我们找出终止条件。
如果一个url解码前和解码后的不发生任何变化,那么我们就可以判断这个url被完全编码出来了。
找出了终止条件,接下来我们调用自身的方法,我只需要将编码后的参数继续调用自身去编码即可。
好了,到这这个问题基本上可以解决掉了。
下面我来上完整的代码的结果
好了,到这里,这个问题基本是可以是解决了。
总结:
- url编码和解码用到的新的api。
- 在面试过程中,凡是提到了不知道有多少次操作的,一般来说都要用到递归算法。
- 递归算法的核心技巧可以参考我前面的文章,这一点很重要,面试非常喜欢问。
最后给大家留一个真实的面试题,也是有关递归算法的。
将一个数组扁平化
var arr = [1,[2,3,[4,5]],[6,7,8,[9]]];
给出一个算法,让返回数组结果:[1,2,3,4,5,6,7,8,9];
这个题目就很直白了,一般来说我们知道用递归算法了。
文章转自csdn[weixin_39918248] # 如何判断字符串已经被url编码_前端面试题(三) 如何解码一个被编码了不知道多少次的url地址...
防止以后链接失效,将文章copy下来,向原创作者【畅哥聊技术】致敬
测试代码
var url = 'https://www.baidu.com?a=xxx&b=12&c=水电费、#的&&d=123'
console.log('编码前',url)
var url2 =encodeURIComponent(url)
console.log('编码1',url2)
url2 =encodeURIComponent(url2)
console.log('编码2',url2)
url2 =encodeURIComponent(url2)
console.log('编码3',url2)
console.log('编码后源url',url)
console.log('解码前:',url2)
let url3 = decodeURIComponent(url2)
console.log('解码1后:',url3)
url3 = decodeURIComponent(url3)
console.log('解码2后:',url3)
url3 = decodeURIComponent(url3)
console.log('解码3后:',url3)
VM1187:2 编码前 https://www.baidu.com?a=xxx&b=12&c=水电费、#的&&d=123
VM1187:4 编码1 https%3A%2F%2Fwww.baidu.com%3Fa%3Dxxx%26b%3D12%26c%3D%E6%B0%B4%E7%94%B5%E8%B4%B9%E3%80%81%23%E7%9A%84%26%26d%3D123
VM1187:6 编码2 https%253A%252F%252Fwww.baidu.com%253Fa%253Dxxx%2526b%253D12%2526c%253D%25E6%25B0%25B4%25E7%2594%25B5%25E8%25B4%25B9%25E3%2580%2581%2523%25E7%259A%2584%2526%2526d%253D123
VM1187:8 编码3 https%25253A%25252F%25252Fwww.baidu.com%25253Fa%25253Dxxx%252526b%25253D12%252526c%25253D%2525E6%2525B0%2525B4%2525E7%252594%2525B5%2525E8%2525B4%2525B9%2525E3%252580%252581%252523%2525E7%25259A%252584%252526%252526d%25253D123
VM1187:9 编码后源url https://www.baidu.com?a=xxx&b=12&c=水电费、#的&&d=123
VM1187:10 解码前: https%25253A%25252F%25252Fwww.baidu.com%25253Fa%25253Dxxx%252526b%25253D12%252526c%25253D%2525E6%2525B0%2525B4%2525E7%252594%2525B5%2525E8%2525B4%2525B9%2525E3%252580%252581%252523%2525E7%25259A%252584%252526%252526d%25253D123
VM1187:12 解码1后: https%253A%252F%252Fwww.baidu.com%253Fa%253Dxxx%2526b%253D12%2526c%253D%25E6%25B0%25B4%25E7%2594%25B5%25E8%25B4%25B9%25E3%2580%2581%2523%25E7%259A%2584%2526%2526d%253D123
VM1187:14 解码2后: https%3A%2F%2Fwww.baidu.com%3Fa%3Dxxx%26b%3D12%26c%3D%E6%B0%B4%E7%94%B5%E8%B4%B9%E3%80%81%23%E7%9A%84%26%26d%3D123
VM1187:16 解码3后: https://www.baidu.com?a=xxx&b=12&c=水电费、#的&&d=123
前端JS获取URL参数的4种方法总结
1.【推荐】使用第三方库 qs
使用第三方库 qs 也可以实现 url 中参数字符的提取,还能实现将参数对象转为 url 参数形式,需要注意的是浏览器 cdn 方式引入时是默认添加到全局对象 window 的 Qs 属性上的,或者import 引入
<script src="https://cdn.bootcdn.net/ajax/libs/qs/6.10.3/qs.min.js"></script>
<script>
let URL = "http://www.baidu.com?product='iPhone 13 Pro'&price=¥9999.00"
function getUrlParams4(url){
// 引入 qs 库时会默认挂在到全局 window 的 Qs 属性上
// console.log(window)
let urlStr = url.split('?')[1]
let result = Qs.parse(urlStr)
// 拼接额外参数
let otherParams = {
num:50,
size:6.1
}
let str = Qs.stringify(otherParams)
let newUrl = url + str
return {result,newUrl}
}
console.log(getUrlParams4(URL))
</script>
2.方法1: 字符串 split 方法
因为一个 url 地址是字符串形式的,所以利用 split 方法将参数提取出来,该方法比较常用,而且容易理解
let URL = "http://www.baidu.com?name=张三&age=25&sex=男&wife=小红"
function getUrlParams(url) {
// 通过 ? 分割获取后面的参数字符串
let urlStr = url.split('?')[1]
// 创建空对象存储参数
let obj = {};
// 再通过 & 将每一个参数单独分割出来
let paramsArr = urlStr.split('&')
for(let i = 0,len = paramsArr.length;i < len;i++){
// 再通过 = 将每一个参数分割为 key:value 的形式
let arr = paramsArr[i].split('=')
obj[arr[0]] = arr[1];
}
return obj
}
console.log(getUrlParams(URL))
3. 利用正则匹配方法
正则匹配功能强大相信很多小伙伴都知道,不仅可以实现在登录注册时的账号、密码、邮箱、手机号等等的验证,还可以非常方便的处理一些字符串(校验、替换、提取等操作),难点在于对正则使用的熟练度,这里就是通过正则提取字符串中需要的字符
let URL = "http://www.baidu.com?name=Tom&friend=Jerry"
function getUrlParams3(url){
// \w+ 表示匹配至少一个(数字、字母及下划线), [\u4e00-\u9fa5]+ 表示匹配至少一个中文字符
let pattern = /(\w+|[\u4e00-\u9fa5]+)=(\w+|[\u4e00-\u9fa5]+)/ig;
let result = {};
url.replace(pattern, ($, $1, $2)=>{
result[$1] = $2;
})
return result
}
console.log(getUrlParams3(URL))
4. 利用 URLSearchParams 方法
在 MDN 中结合两种方法实现参数的获取:1. 使用 `new URLSearchParams(url)` 方法,返回一个 URLSearchParams 对象,再调用 `entries()` 方法返回一个可迭代对象(Iterator);2. 使用 `Object.fromEntries(iterable)` 方法转化为普通对象
**特别注意 **:URLSearchParams 方法不仅可以获取参数,还可以将参数对象转为 字符串,详细用法可查看 MDN 中的介绍,并且该方法存在浏览器兼容性问题。
let URL = "http://www.baidu.com?name=Jack&age=25&sex=men&wife=Lucy"
function getUrlParams2(url) {
let urlStr = url.split('?')[1]
const urlSearchParams = new URLSearchParams(urlStr)
const result = Object.fromEntries(urlSearchParams.entries())
return result
}
console.log(getUrlParams2(URL))