为什么JS扩展运算符克隆response对象时headers属性为undefined?
问题根因
对象扩展运算符(...)的拷贝边界是固定的:仅复制源对象自身持有的、可枚举的自有属性,不会拷贝原型链上的继承属性,也不会拷贝源对象上标记为不可枚举的属性。
request-promise返回的response是封装了Node.js原生http.IncomingMessage的类实例对象,你访问的response.headers并不满足「自有可枚举属性」的要求:
- 它要么是定义在类原型上的getter访问器属性
- 要么是挂载在实例上,但被标记为
enumerable: false的不可枚举属性
这种前提下直接执行{...response}做展开拷贝时,JS引擎遍历源对象的可枚举自有属性列表时根本识别不到headers字段,自然不会把它复制到新对象respObj中,最终读取respObj.headers就会返回undefined。
手动赋值headers生效的逻辑
当你显式写{...response, headers: response.headers}时,代码会主动触发response对象上headers的取值逻辑,拿到真实的响应头对象后,直接将其作为新对象的自有可枚举属性挂载到respObj上,所以可以正常读取到值。
属性特征验证方式
你可以在拿到response对象后执行以下代码,直接验证headers的属性性质:
// 返回false即说明headers不是response的自有属性 console.log(response.hasOwnProperty('headers')) // 返回undefined说明headers定义在原型链上;如果返回配置对象,其中enumerable为false则说明是不可枚举自有属性 console.log(Object.getOwnPropertyDescriptor(response, 'headers'))
这类属性丢失问题不是request-promise独有的:所有第三方库返回的类实例对象,只要属性是原型继承、不可枚举、或通过getter代理实现的,直接用扩展运算符做浅拷贝都会出现同类问题。
内容的提问来源于stack exchange,提问作者kirithika M
相关产品推荐
相关产品推荐

