我正在开发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新手,所以问题是:
Object.assign()
我到底缺少什么? 虽然返回合并的对象是多余的(.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);
这是DOM元素上style
属性的古怪之处,这是对Web浏览器早期的遗憾,它在Web浏览器中添加了一些内容...怀着一些非常非常奇怪的语义的方式。
当您read
元素的style
属性时,您将获得一个具有内联样式属性的对象。但是,当您对它进行[[write时,您所写的内容将被视为字符串或null
。 (尽管officially,它应该是只读的。但是,在当今的浏览器中,并没有那样对待它。)故事的寓意:不要写它(除非您要写null
以完全清除它)。所以当您这样做:
sidePanel.style = Object.assign(sidePanel.style, sidePanelStyle);
...发生的事情是:
sidePanel.style
,因为Object.assign
会写入其第一个参数中给出的对象,然后再写入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
的第一个参数。