【问题标题】:Assigning a subset of properties with the Object.assign() method使用 Object.assign() 方法分配属性子集
【发布时间】:2020-05-16 11:08:32
【问题描述】:

我正在开发一个 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() 返回一个合并的对象,根据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);

【问题讨论】:

  • 也就是说,sidePanel.style = Object.assign(sidePanel.style, sidePanelStyle); 中的sidePanel.style = Object.assign(sidePanel.style, sidePanelStyle); 没有任何理由。 Object.assign 确实返回了合并的对象,但是它将对象合并到第一个对象中,因此如果您已经引用了该对象,则无需进行分配。只需Object.assign(sidePanel.style, sidePanelStyle); 就足够了。 (如果您正在创建它,它会返回它作为第一个参数接收的对象,例如const obj = Object.assign({}, ...);。)
  • 插入了一个 sn-p

标签: javascript object dom iframe assign


【解决方案1】:

这是 DOM 元素上的 style 属性的一个怪癖,这是对早期网络浏览器的不幸倒退,当时添加了一些东西......不管用什么非常非常奇怪的语义。

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

故事的寓意:不要给它写信(除非你写 null 来彻底清除它)。

所以当你这样做时:

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

...发生的事情是:

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

  2. 它返回的对象(也是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 的第一个参数。

【讨论】:

  • 很好的答案,谢谢。我有这种直觉,它与.style 实现有关,但并不明显。
  • 确实,非常不明显。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-03
  • 2018-06-13
  • 2012-04-22
  • 1970-01-01
  • 2021-06-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多