如何告诉 postMessage 结构化克隆忽略属性?

How to tell postMessage structured clone to ignore properties?

我正在做一个项目,我需要在 iframe 中创建一个对象,然后将所述对象发送给父级 window。

问题是 postMessage 失败,因为无法克隆对象 (DataCloneError),因为它具有函数 (callback) 属性.

更复杂的是,存在循环关系,按钮列表包含按钮,每个按钮都有对其父列表的引用。

如果这是使用 JSON.stringify 而不是结构化克隆,可以覆盖按钮上的 toJSON 并避免发送 callback 并将 list 替换为 listId 来避免循环引用的情况。是否有等同于 toJSON 的结构化克隆,允许在保持循环关系或其他解决方案的同时忽略 callback

这是可重现错误的情况的大致要点:

class ButtonList {
    constructor() {
        this.buttons = [];
    }

    addButton(button) {
        if (!this.buttons.includes(button)) {
            this.buttons.push(button);
            button.setList(this);
        }
        return this;
    }
}

class Button {
    setList(list) {
        if (!list) return this;
        if (this.list !== list) {
            this.list = list;
            list.addButton(this);
        }
        return this;
    }

    setCallback(callback) {
        this.callback = callback;
        return this;
    }

    getCallback() {
        return this.callback;
    }

    runCallback() {
        if (!this.callback) return this;
        this.callback();
        return this;
    }
}

const list = new ButtonList();
const button = new Button().setList(list).setCallback(() => console.log('Hello'));
window.postMessage(list, '*');

// DataCloneError: The object could not be cloned.

父 window 不需要知道回调,但需要知道任何其他属性。

使用 Object.assign 创建一个具有覆盖属性的新对象并通过 postMessage 发送它。

const foo = {
  bar: 'bar',
  list: { bla: 'bla' },
  baz: function() {
    console.log('baz')
  }
}

const serializable = Object.assign({}, foo, { 
  list: 3,
  baz: undefined 
})

console.log(serializable)