URL解码函数优化
我将帮你优化这段URL解析代码,使其更简洁、易读。以下是优化后的版本:
function urlDecode(url) {
const urlObj = {
scheme: undefined,
addr: undefined,
port: undefined,
path: "",
args: "",
hash: ""
};
// 提取hash部分
const extractHash = (url) => {
const hashIndex = url.indexOf('#');
return hashIndex === -1
? { path: url, hash: "" }
: { path: url.substring(0, hashIndex), hash: url.substring(hashIndex) };
};
// 提取参数部分
const extractArgs = (url) => {
const argIndex = url.indexOf('?');
return argIndex === -1
? { path: url, args: "" }
: { path: url.substring(0, argIndex), args: url.substring(argIndex) };
};
// 判断地址类型(IPv4或IPv6)
const getAddrType = (addr) => addr.startsWith('[') ? "v6" : "v4";
// 处理地址和端口
const processAddress = (addr) => {
if (!addr) return;
if (getAddrType(addr) === "v4") {
const colonPos = addr.indexOf(':');
if (colonPos === -1) {
urlObj.addr = addr;
} else {
[urlObj.addr, urlObj.port] = [addr.substring(0, colonPos), addr.substring(colonPos + 1)];
}
} else { // IPv6
const bracketColonPos = addr.indexOf(']:');
if (bracketColonPos === -1) {
urlObj.addr = addr.slice(1, -1); // 移除方括号
} else {
[urlObj.addr, urlObj.port] = [
addr.substring(1, bracketColonPos),
addr.substring(bracketColonPos + 2)
];
}
}
};
// 主处理逻辑
let processedUrl = url.trim();
// 提取hash部分
let { path, hash } = extractHash(processedUrl);
[processedUrl, urlObj.hash] = [path, hash];
if (!processedUrl) return urlObj;
// 确定协议和起始位置
let startPos;
if (processedUrl.startsWith('https://')) {
startPos = 8;
[urlObj.scheme, urlObj.port] = ['https', '443'];
} else if (processedUrl.startsWith('http://')) {
startPos = 7;
[urlObj.scheme, urlObj.port] = ['http', '80'];
} else if (processedUrl.startsWith('//')) {
startPos = 2;
}
// 如果没有协议信息,直接处理路径和参数
if (startPos === undefined) {
({ path, args }= extractArgs(processedUrl));
[urlObj.path, urlObj.args] = [path || "", args || ""];
return urlObj;
}
// 处理剩余部分(地址+路径/参数)
let remainingUrl = processedUrl.slice(startPos);
// 查找第一个斜杠或问号作为分隔点
let separatorIndex;
for (let i=0; i<remainingUrl.length; i++) {
if (remainingUrl[i] === '/' || remainingUrl[i] === '?') {
separatorIndex=i;
break;
}
}
let addressPart;
if (separatorIndex !== undefined && separatorIndex >0){
addressPart=remainingUrl.slice(0,separatorIndex);
remainingUrl=remainingUrl.slice(separatorIndex);
({path='',args=''}=extractArgs(remainingUrl));
[urlObj.path ,urlObj.args]=[path ,args];
processAddress(addressPart);
}else{
processAddress(addressPart=remainingUrl);
({path='',args=''}=extractArgs(""));
[urlObj.path ,urlObj.args]=[path ,args];
}
return Object.fromEntries(
Object.entries(urlObj).filter(([_,value]) => value !== "")
);
}
优化点说明:
函数拆分:将大函数拆分为多个小功能函数,每个函数只做一件事。
使用现代语法:
startsWith()
/slice()
等字符串方法替代手动索引检查Object.fromEntries()
简化对象创建
更清晰的变量命名:
extractHash
代替cutHash
processAddress
代替内联的地址处理逻辑
减少重复代码:
- IPv4/IPv6处理的共同逻辑合并
更好的默认值处理:
- 使用解构赋值的默认值避免空字符串检查
更安全的边界条件处理:
- 所有子字符串操作都有边界检查
最终清理空值:
Object.fromEntries()
过滤掉空字符串属性
这个版本保持了原有功能,但结构更清晰,可读性更好,也更易于维护。
内容由零声教学AI助手提供,问题来源于学员提问