模板字符串内部出现反引号时,必须转义成 \`。内容量大或来自外部时,转义很烦。
方案一:数组 join(最稳)
完全不需要考虑转义,任意字符都行:
const sql = [
"SELECT * FROM `users`",
"WHERE `status` = 'active'",
"AND `name` LIKE `%test%`",
].join('\n');
大段 HTML、SQL、Prompt 推荐这种写法——可读性好,又不怕特殊字符。
方案二:String.raw(不处理转义序列)
const pattern = String.raw`\d+\.\d+`;
// 等价于 "\\d+\\.\\d+"
// 不需要手动双反斜杠
在 String.raw 里,反斜杠不被解释为转义符,但反引号仍然需要转义,所以它主要解决的是 \n、\t 这类转义序列问题,而不是反引号嵌套问题。
const py = String.raw`
print("hello")
# 反引号仍需 \`
`;
方案三:外部文件(大段文本首选)
// Vite / webpack 环境
import template from './prompt.txt?raw';
import html from './template.html?raw';
// Node.js 环境
const template = fs.readFileSync('./prompt.txt', 'utf8');
AI Prompt、HTML 模板、大段代码存外部文件,完全不需要处理引号或转义问题,也方便单独编辑和版本追踪。
油猴脚本里 hook window 属性
油猴脚本里经常需要拦截页面的某个全局变量或 API,Object.defineProperty 比整体 Proxy 更可靠:
// hook 单个属性
const rawFetch = window.fetch;
Object.defineProperty(window, 'fetch', {
configurable: true,
get() {
return function(...args) {
console.log('fetch called:', args[0]);
return rawFetch.apply(this, args);
};
}
});
整体 new Proxy(window, ...) 只是创建了一个代理对象,不会改变其他代码里访问的真实 window,所以通常没有实际效果。Object.defineProperty 是直接修改全局对象,才能真正拦截到。
hook document.cookie
const cookieSetter = Document.prototype.__lookupSetter__('cookie');
const cookieGetter = Document.prototype.__lookupGetter__('cookie');
Object.defineProperty(Document.prototype, 'cookie', {
configurable: true,
get() {
return cookieGetter.call(this);
},
set(val) {
console.log('cookie set:', val);
cookieSetter.call(this, val);
}
});
安全读取 cookie 值
正则匹配 cookie 时,结尾分号可能没有(最后一项),用 [^;]* 比 .*?; 更稳:
function getCookie(name) {
const match = document.cookie.match(
new RegExp(`${name}=([^;]*)`)
);
return match ? match[1] : undefined;
}
[^;]* 含义:匹配零个或多个不是分号的字符,不管 cookie 是不是最后一项都能正确提取。
