实现QueryString
题目要求:
- 给定一个对象
{a:1,b:2,c:[1,2] }
- 输出一个查询字符串
?a=1&b=2&c=1,2
要求给出 实现QueryString 构造函数身上的 stringify 和 parse 方法
stringify
我们先来实现一下stringify 方法
首先呢 我们先定义构造函数
- 接收两个参数 pre : 前缀 和seq : 分隔符
function QueryString(pre,seq){
}
在这个构造函数身上添加一个stringify 方法
- 这个函数接收一个对象
- 遍历这个对象
- 拿到key 和 value 值 以及 seq 分隔符 进行拼接
- 然后追加在str 身上
- 最后针对str 身上的最后的分割符 进行 去除 (
slice
||substring
)
QueryString.prototype.stringify = function(obj){
//1. 定义字符串
let str = this.pre // 定义一个字符串 然后值为传过来的前缀
//2. 遍历obj 对象
for(let key in obj){
// key : 为obj 对象的key值 即 键名
// obj[key] : 通过这种方式取到对应键值的value值
// 模板字符串 进行拼接即可
// 最后追加在str 变量身上
str += `${
key}=${
obj[key]}${
this.seq}`
}
return str.slice(0,-1) // 去除字符串最后的分隔符 然后进行返回
}
好, 第一种原始的方法 我们 已经介绍完毕了剩下我们介绍一种使用es6 新api 解决的方案 只需要一行代码 即可完成功能呢
Object.keys()
静态方法返回一个由给定对象自身的可枚举的字符串键属性名
组成的数组。map()
方法创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数
后的返回值组成join()
方法将数组中所有元素连接为一个字符串。
QueryString.prototype.stringify = function (obj) {
return this.pre + Object.keys(obj).map(k => k + '=' + obj[k]).join(this.seq)
}
我们来进行拆解一下:
this.pre =
?
Object.keys(obj) =
[a,b,c]
[a,b,c].map(k = > console.log(k,obj[k]))
a 1
b 2
c [1,2]
k + '=' + obj[k]
a=1
b=2
c=1,2
因为map 之后 会返回一个新的数组 经过上面的处理之后 我们目前的数组变成了
['a=1', 'b=2', 'c=1,2']
再之后 进行 join 拼接 得到一个含有指定符号(取决于传给join 的 符号
)的字符串
'a=1&b=2&c=1,2'
再之后 加上前缀 this.pre
即 ?
即可完成了
?a=1&b=2&c=1,2
parse
题目要求:
输入
'?a=1&b=2&c=1,2'
输出
{a: '1', b: '2', c: ['1','2']}
好嘞,我们开始吧
还是和上面一样在构造函数的原型上添加方法 该方法接收一个字符串为参数
QueryString.prototype.parse = function (str) {
}
首先我们需要生成一个对象, 因为题目最后要求输出一个对象,也表示我们需要在该方法return一个对象
QueryString.prototype.parse = function (str) {
// 生成一个对象 最后需要返回u
let result ={
}
return result
}
其次我们先打印一个str (这里已经调用该方法 并传入'?a=1&b=2&c=1,2'
) 了
?a=1&b=2&c=1,2
这里我们先观察一下这个字符串, 可以划分一下
? || a=1 || & || b=2 || & || c=1,2
我们先把?
作为标识符号即 this.pre 即我们之前在构造函数身上添加的属性 进行分割
下面的代码将会返回
str.split(this.pre) // [' ', 'a=1&b=2&c=1,2']
接下来我们可以直接使用索引
取出这个数组第二个值a=1&b=2&c=1,2
a=1 || & || b=2 || & || c=1,2
此时我们继续重复上面的步骤来, 继续进行分割,按照`分隔符
`
str.split(this.pre)[1].split(this.seq) // ['a=1', 'b=2', 'c=1,2']
好,现在我们已经拿到我们想要的内容了,接下来呢 我们想的是取
a ---> key
1 ---> value
然后进行obj
对象的赋值
我们现在是个数组, 然后针对这样的数组 我们需要取出里面的每一项用
forEach
是一个用于数组的方法,用于遍历数组的每个元素并执行指定的操作。它接受一个回调函数作为参数,并将数组的每个元素依次传递给回调函数进行处理。
const s1 = str.split(this.pre)[1].split(this.seq)
s1.forEach((item)=>{
console.log(item) //
})
item:
a=1
b=2
c=1,2
看到=
号,我们还需要进行分割,因为这样不仅可以去除 = , 还有就是 把 a
和 1
放入一个数组里面,并且独立的项
即 item.split('=') --> ['a','1']
然后分别抽离key 和 value
即 const k
= item.split('=')[0] const v
= item.split('=')[1]
再给对象赋值之前还有一步 原本c 是一个数组,所以我们需要进行if判断
if (v.includes(',')) {
// 继续分割 因为'1,2' 字符 按照,号分割 -->> ['1','2']
result[k] = v.split(',')
} else {
result[k] = v
}
好了, 至此代码结束
下面是完整的代码, 其实没有多少, 主要考察 字符串切割split()
QueryString.prototype.parse = function (str) {
// 生成一个对象 最后需要返回u
let result = {
}
// 首先我们先进行字符的分割 --> 拿到我们主要内容
const s = str.split(this.pre)s[1].split(this.seq)
// 好,这个时候我们已经拿到我们想要的内容, 然后进行
// 循环遍历
s.forEach((item) => {
// 解构赋值 -- 一一对应
const [k,v] = item.split('=')
if (v.includes(',')) {
result[k] = v.split(',')
} else {
result[k] = v
}
})
return result
}