未捕获的TypeError:无法设置仅具有getter的#<HTMLElement>的属性样式

gma*_*man 6 javascript google-chrome

以下代码在Chrome中失败,Safari在Firefox中运行良好

"use strict";
document.body.style = "background-color: green;";
Run Code Online (Sandbox Code Playgroud)
<p>background should be green</p>
Run Code Online (Sandbox Code Playgroud)

删除"使用严格",它的工作原理.

这是Chrome和Safari中的错误还是Firefox中的错误?MDN表示设置style有效.

Ori*_*iol 10

问题

并非所有浏览器都支持分配包含CSS声明块的文本表示的字符串到style属性.

element.style = styleString; // Might not work
Run Code Online (Sandbox Code Playgroud)

解决方法

作为解决方法,您可以将其设置为内容属性或cssText属性:

element.setAttribute('style', styleString);
Run Code Online (Sandbox Code Playgroud)
element.style.cssText = styleString;
Run Code Online (Sandbox Code Playgroud)

标准行为

在符合DOM L2 Style和ES5的旧浏览器上,分配应该

  • 投入严格模式
  • 在非严格模式下被忽略.

在符合CSSOM和ES5的较新浏览器上,分配应该

  • 一直工作

全部细节

根据DOM Level 2 Style规范,该style属性在ElementCSSInlineStyle界面中定义如下:

interface ElementCSSInlineStyle {
  readonly attribute CSSStyleDeclaration  style;
};
Run Code Online (Sandbox Code Playgroud)

因此,style应该将属性实现为具有getter但没有setter 的accessor属性.

Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'style'); /* {
  configurable: true,
  enumerable: true,
  get: function(){...},
  set: undefined
} */
Run Code Online (Sandbox Code Playgroud)

根据ECMAScript 5,当您尝试为某个属性分配一些值时,必须在严格模式下抛出错误:

当在严格模式代码中发生赋值时, LeftHandSide也可能不是具有属性值{[[Set]]:undefined } [...] 的访问者属性的引用[...].在这些情况下,抛出TypeError异常.

但是,DOM L2 Style被新的CSS对象模型(CSSOM)取代.

根据该规范,style接口的IDL属性由ElementCSSInlineStyle,实现HTMLElement,被定义为[PutForwards]扩展属性:

[NoInterfaceObject]
interface ElementCSSInlineStyle {
  [SameObject, PutForwards=cssText] readonly attribute CSSStyleDeclaration style;
};
Run Code Online (Sandbox Code Playgroud)

这意味着设置style属性必须像设置其中cssText一个CSSStyleDeclaration.因此,那些必须是等价的:

element.style = styleString;
element.style.cssText = styleString;
Run Code Online (Sandbox Code Playgroud)

这就是为什么它适用于较新的浏览器.