使用 Object.assign() 方法分配属性子集

Assigning a subset of properties with the Object.assign() method

我正在开发 chrome 扩展,我正在使用 iframe 元素创建侧面板。 我有一个对象存储相应 iframe:

的样式
const sidePanelStyle = {
    background: 'white',
    // some other vars 
};

我创建 iframe 并分配我的设置:

let sidePanel = document.createElement('iframe');
Object.assign(sidePanel.style, sidePanelStyle);

一切正常,但在我之前

sidePanel.style = Object.assign(sidePanel.style, sidePanelStyle);

它没有将任何东西合并到 sidePanel.style 中(我预计 .assign() returns 是一个合并的对象,根据 MDN)。

我是 JS 新手,所以问题是:

  1. Object.assign() 我到底错过了什么?
  2. 将多个设置属性分配给现有框架中的对象的最佳做法是什么,将它们保留在我的源代码中的最佳做法是什么(一个单独的 模块?一个或多个对象?等)。

虽然返回合并的对象是多余的(.assign() 方法将所有内容合并到第一个参数中),但我仍然很好奇为什么它在返回对象时不起作用。

const sidePanelStyle = {
 background: 'gray',
 height: '100%',
 padding: '20px',
 width: '400px',
 position: 'fixed',
 top: '0px',
 right: '0px',
 zIndex: '9000000000000000000',
};

let sidePanel = document.createElement('iframe');
// this works fine
// Object.assign(sidePanel.style, sidePanelStyle);

// this doesn't
sidePanel.style = Object.assign(sidePanel.style, sidePanelStyle);


document.body.appendChild(sidePanel);

这是 style 属性 在 DOM 元素上的一个怪癖,这是对早期 Web 浏览器添加了一些东西的不幸倒退... willy nilly 有一些非常非常奇怪的语义。

当您 读取 元素的 style 属性 时,您会得到一个具有内联样式属性的对象。但是当你向它写入时,你写入的内容将被视为字符串或null。 (尽管 officially,它应该是只读的。但是在今天的浏览器中它不是这样处理的。)

这个故事的寓意:不要写它(除非你写 null 来完全清除它)。

所以当你这样做时:

sidePanel.style = Object.assign(sidePanel.style, sidePanelStyle);

...发生的事情是:

  1. 样式成功添加到sidePanel.style,因为Object.assign写入第一个参数给定的对象,然后

  2. 它returns(也sidePanel.style)的对象被转换为字符串并解释为样式属性。 (不过,同样,它应该是只读的。)

但是当你把它转换成字符串时,得到的字符串是"[object CSSStyleDeclaration]",它不能转换成样式,所以你擦掉了元素上的样式。

这里有一个更简单的演示:

const example = document.getElementById("example");
example.style.color = "blue";
setTimeout(function() {
    console.log("example.style.color before: " + example.style.color);
    // Assigning it to itself, which is effectively what
    // your code with `Object.assign` was doing
    example.style = example.style;
    console.log("example.style.color after:  " + example.style.color);
    console.log("String(example.style): " + String(example.style));
}, 800);
<div id="example">This is the example div</div>

如您所见,无论如何都没有理由回写它,因为属性已添加到它,因为它是 Object.assign.

的第一个参数