链式调用虽然快乐,可每个方法后面的 return this
略显繁琐与丑陋,括号与引号也未免太多。
例如下面这个简单的logger
new Logger()
.addLabel("warn", "l4", "登录", "游客", "error")
.addContent("失败")
.addContent("密码不对")
.end();
你可能已经对这样的封装习以为常了,但其实他还能这样写!
Log.warn.l4.label("登录", "游客").log("失败").error.密码不对;
我觉得后者有一种简洁美
具体实现如下
class Logger {
label: string[] = [];
content: unknown[] = [];
addLabel(...label: string[]) {
this.label.push(...label);
return this;
}
addContent(content: unknown) {
this.content.push(content);
return this;
}
end() {
// 做一些存储打印之类的操作
console.log(this);
}
}
function getLog() {
const logger = new Logger();
/** 访问链路 */
const propertyLink: (string | number | symbol)[] = [];
const self = (new Proxy(/** 目标不重要,因为实际上使用 target */ getLog, {
get(target, property, receiver) {
propertyLink.push(property);
// console.log(property);
if (/** 表等级用 */ typeof property === "string" && /l\d+/.test(property)) {
logger.addLabel(property);
} else if (/** 直接添加标签 */ typeof property === "string" && ["warn", "error"].includes(property)) {
logger.addLabel(property);
} else if (/** 可以调用的方法 */ typeof property === "string" && ["log", "label"].includes(property)) {
// 调用则添加内容
} else {
//over
logger.addContent(property);
return logger.end();
}
return self;
},
apply(target, thisArg, argumentsList) {
const previousProperty = propertyLink[propertyLink.length - 1];
if (previousProperty === "label") {
logger.addLabel(...argumentsList);
} else if (previousProperty === "log") {
logger.addContent(argumentsList);
}
return self;
},
}) as any) as Log;
return self;
}
const Log = new Proxy(getLog(), {
get() {
return getLog();
},
});
type Log = {
error: Log;
warn: Log;
info: Log;
label: (...lables: string[]) => Log;
l1: Log;
l2: Log;
l3: Log;
l4: Log;
l5: Log;
l6: Log;
l7: Log;
l8: Log;
l9: Log;
/** 具体消息 */
[k: string]: void | Log | any;
log: (...arg: unknown[]) => Log;
end: void;
};
Log.error.l9.错了呀;
Log.error.l9.warn.错了呀;
Log.error.l4.那天夕阳下的奔跑是我逝去的青春;
Log.warn.l4.log("有毒?").end;
Log.warn.l4
.label("登录")
.label("游客")
.log("失败").end;
Log.warn.l4.label("登录", "游客").log("失败").error.密码不对;
new Logger()
.addLabel("warn", "l4", "登录", "游客", "error")
.addContent("失败")
.addContent("密码不对")
.end();
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。