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

时间:2019-01-31 16:19:56

标签: javascript postmessage structured-clone

我正在一个项目中,需要在iframe中创建一个对象,然后将其发送到父窗口。

问题是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.

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

1 个答案:

答案 0 :(得分:1)

使用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)