JavaScript:如何让类实例通过引用获取对象属性(无需extends)
解决方案:让类实例属性与原对象实例同步(无需嵌套访问)
你遇到的核心问题是Object.assign做的是值拷贝,没法同步原对象的更新。下面两个方案能实现直接访问类实例属性,同时和原对象保持引用同步:
方案一:用Proxy代理原对象
通过ES6的Proxy拦截类实例的属性读写操作,直接映射到原对象上,不管是修改原对象还是类实例,两边都会同步:
const obj = { speed: 105 } class Car { constructor(obj) { return new Proxy(this, { get(target, prop) { // 先读原对象的属性,没有再读实例自身的 return prop in obj ? obj[prop] : target[prop]; }, set(target, prop, value) { // 写属性时同步到原对象 if (prop in obj) { obj[prop] = value; return true; } target[prop] = value; return true; } }); } } const c = new Car(obj); console.log(c.speed); // 输出105 obj.speed = 120; console.log(c.speed); // 输出120 c.speed = 150; console.log(obj.speed); // 输出150
这个方案的好处是能自动处理后续给原对象新增的属性(如果需要,还能调整拦截逻辑支持动态新增属性的同步),代码也比较简洁。
方案二:动态绑定getter和setter
遍历原对象的属性,给类实例的每个属性绑定对应的getter和setter,每次读写都直接操作原对象:
const obj = { speed: 105 } class Car { constructor(obj) { Object.keys(obj).forEach(prop => { Object.defineProperty(this, prop, { get() { return obj[prop]; }, set(value) { obj[prop] = value; }, enumerable: true, configurable: true }); }); } } const c = new Car(obj); console.log(c.speed); // 输出105 obj.speed = 120; console.log(c.speed); // 输出120 c.speed = 150; console.log(obj.speed); // 输出150
这个方案兼容性更好(适合不支持Proxy的旧环境),但只同步构造时原对象已有的属性,后续新增的属性需要手动添加getter/setter。
内容的提问来源于stack exchange,提问作者Alex Mortez
相关产品推荐
相关产品推荐

