最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - create structured clone of Proxy - Stack Overflow

programmeradmin2浏览0评论

I have a class that returns a Proxy from the constructor. When I try to store instances of this class in IndexedDB, or send the object using window.postMessage(), I receive an error stating that the object could not be cloned. It appears that the structured clone algorithm cannot handle Proxy objects.

The following code demonstrates the error:

class MyClass {
  constructor() {
    return new Proxy(this, {
      set(target, prop, val, receiver) {
        console.log(`"${prop}" was set to "${val}"`);
        return Reflect.set(target, prop, val, receiver);
      }
    });
  }
}

const obj = new MyClass;

try {
  window.postMessage(obj,'*');
} catch(err) {
  console.error(err);

}

I have a class that returns a Proxy from the constructor. When I try to store instances of this class in IndexedDB, or send the object using window.postMessage(), I receive an error stating that the object could not be cloned. It appears that the structured clone algorithm cannot handle Proxy objects.

The following code demonstrates the error:

class MyClass {
  constructor() {
    return new Proxy(this, {
      set(target, prop, val, receiver) {
        console.log(`"${prop}" was set to "${val}"`);
        return Reflect.set(target, prop, val, receiver);
      }
    });
  }
}

const obj = new MyClass;

try {
  window.postMessage(obj,'*');
} catch(err) {
  console.error(err);

}

Can anyone suggest a workaround for this problem? I see two potential solutions, but I don't know how I might implement them:

  1. Do not return a Proxy from the constructor, but maintain the Proxy functionality within the class declaration somehow.

  2. Alter the Proxy instance so that it works with the structured clone algorithm.

EDIT: The following, simpler code also demonstrates the structured clone error:

const p = new Proxy({}, {});
window.postMessage(p, '*');

Share Improve this question asked May 22, 2017 at 17:30 dwhiebdwhieb 1,84620 silver badges31 bronze badges 1
  • Having just learnt that this is a thing. All I can do is laugh. – MrYellow Commented Jan 24, 2023 at 22:50
Add a ment  | 

1 Answer 1

Reset to default 4

You can save the original, non-proxied object in a class property, and use it when you want to pass it to postMessage. You can change the constructor to have an optional parameter which will be passed to the proxy instead of this. This way you can recreate the object by passing it to the constructor.

class MyClass {
  constructor(original = this) {
    this.original = original;
    return new Proxy(original, {
      set(target, prop, val, receiver) {
        console.log(`"${prop}" was set to "${val}"`);
        return Reflect.set(target, prop, val, receiver);
      }
    });
  }
  export() {
    return this.original;
  }
  static import(original) {
    return new MyClass(original);
  }
}

const obj = new MyClass;

obj.test = 1;
console.log(MyClass.import(obj.export()).test);
MyClass.import(obj.export()).test = 2;

try {
  window.postMessage(obj.export(), '*');
} catch(err) {
  console.error(err);
}

发布评论

评论列表(0)

  1. 暂无评论