如何修改JavaScript Request对象属性并实现简洁克隆?
如何简洁克隆并修改JavaScript Request对象
为什么Object.getOwnPropertyNames无法获取Request属性
Request实例的核心属性(如method、redirect、headers等)并非定义在实例自身,而是作为访问器属性挂载在Request.prototype原型链上。Object.getOwnPropertyNames()仅能获取对象自身的属性,所以会返回空数组。
获取Request所有可访问属性的方法
我们可以遍历Request.prototype的属性,筛选出那些具备getter的访问器属性(排除clone()这类方法):
function getRequestProperties() { const proto = Request.prototype; const props = []; // 遍历原型链的所有属性 for (const key of Object.getOwnPropertyNames(proto)) { const descriptor = Object.getOwnPropertyDescriptor(proto, key); // 筛选出有getter的访问器属性,排除构造函数 if (descriptor.get && typeof descriptor.get === 'function' && key !== 'constructor') { props.push(key); } } return props; } // 测试:获取所有Request属性 console.log(getRequestProperties()); // 输出示例: ["method", "url", "headers", "redirect", "mode", "credentials", ...]
通用的Request克隆与修改函数
基于上述方法,我们可以创建一个简洁的克隆函数,自动复制原Request的所有属性,并允许传入修改项覆盖:
function cloneRequest(original, overrides = {}) { const props = getRequestProperties(); // 收集原Request的所有属性值 const requestOptions = {}; for (const prop of props) { // 特殊处理headers:创建新的Headers实例避免引用问题 if (prop === 'headers') { requestOptions[prop] = new Headers(original[prop]); } else { requestOptions[prop] = original[prop]; } } // 合并修改项 Object.assign(requestOptions, overrides); // 返回新的Request实例 return new Request(original.url, requestOptions); } // 使用示例 const originalRequest = new Request("https://example.com", { method: "GET", redirect: "follow", headers: { "Content-Type": "application/json" } }); // 克隆并修改redirect属性 const newRequest = cloneRequest(originalRequest, { redirect: "manual" }); console.log(newRequest.redirect); // "manual" console.log(newRequest.headers.get('Content-Type')); // "application/json"
注意事项
- Body的一次性读取限制:如果原Request的
body已经被读取过(比如调用过text()、json()),那么克隆后的Request的body会为空。这是因为Request的body是可读流,只能被消费一次。如果需要克隆已读取过body的Request,需要提前缓存body内容并重新传入。 - 部分属性的不可修改性:少数Request属性(如
bodyUsed)是只读的,无法通过构造函数修改,克隆时会自动继承原属性值。
内容的提问来源于stack exchange,提问作者jcubic
相关产品推荐
相关产品推荐

