十一、DOM2 和DOM 3

  DOM 1 级主要定义的是 HTML 和 XML 文档的底层结构。

  DOM2 和 DOM3 级则在这个结构的基础上引入了更多的的交互能力,也支持了更高级的 XML 特性。

  为此,DOM2 和 DOM3 级分为许多模块(模块之间具有某种关联),分别描述了 DOM 的某个非常具体的子集。这些模块如下。

  • DOM2 级核心(DOM Level 2 Core):在 1 级核心基础上构建,为节点添加了更多方法和属性。
  • DOM2 级视图(DOM Level 2 Views):为文档定义了基于样式信息的不同视图。
  • DOM2 级 HTML(DOM Level 2 HTML):在 1 级 HTML 基础上构建,添加了更多属性、方法和新接口。
  • DOM2 级事件(DOM Level 2 Events):说明了如何使用事件与 DOM 文档交互。
  • DOM2 级样式(DOM Level 2 Style):定义了如何以编程方式来访问和改变 CSS 样式信息。
  • DOM2 级遍历和范围(DOM Level 2 Traversal and Range):引入了遍历 DOM 文档和选择其特定部分的新接口。

  这里探讨除 “DOM2 级事件” 之外的所有模块。

1、DOM 变化

  DOM2 级和 3 级的目的在于扩展 DOM API,以满足操作 XML 的所有需求,同时提供更好的错误处理及特性检测能力。从某种意义上讲,实现这一目的很大程度意味着对命名空间的支持。
  “DOM2 级核心” 没有引入新类型,它只是在 DOM1 级的基础上通过增加新方法和新属性来增强了既有类型。
  “DOM3 级核心” 同样增强了既有类型,但也引入了一些新类型。

  类似的,“DOM2 级视图” 和 “DOM2 级 HTML” 模块也增强了 DOM 接口,提供了新的属性和方法。由于这两个模块很小,因此我们将把它们与 “DOM2 级核心” 放在一起,讨论基本 JavaScript 对象的变化。
  可以通过下列代码来确定浏览器是否支持这些 DOM 模块。

var supportsDOM2Core = document.implementation.hasFeature("Core", "2.0");
var supportsDOM3Core = document.implementation.hasFeature("Core", "3.0");
var supportsDOM2HTML = document.implementation.hasFeature("HTML", "2.0");
var supportsDOM2Views = document.implementation.hasFeature("Views", "2.0");
var supportsDOM2XML = document.implementation.hasFeature("XML", "2.0"); 

1.1、针对 XML 命名空间的变化

  有了 XML 命名空间,不同 XML 文档的元素就可以混合在一起,共同构成格式良好的文档,而不必担心发生命名冲突。
  从技术上说,HTML 不支持 XML 命名空间,但 XHTML 支持 XML 命名空间。因此,本节给出的都是 XHTML 的示例。
  命名空间要使用 xmlns 特性来指定。XHTML 的命名空间是 http://www.w3.org/1999/xhtml,在任何格式良好 XHTML 页面中,都应该将其包含在元素中,如下面的例子所示。


    
        Example XHTML page
    
    
        Hello world!
    

  对上述例子而言,其中的所有元素默认都被视为 XHTML 命名空间中的元素。要想明确地为 XML 命名空间创建前缀,可以使用 xmlns 后跟冒号,再后跟前缀,如下所示。


    
        Example XHTML page
    
    
        Hello world!
    

  这里为 XHTML 的命名空间定义了一个名为 xhtml 的前缀,并要求所有 XHTML 元素都以该前缀开头。有时候为了避免不同语言间的冲突,也需要使用命名空间来限定特性,示例:


    
        Example XHTML page
    
    
        Hello world!
    

  这个例子中的特性 class 带有一个 xhtml 前缀。在只基于一种语言编写 XML 文档的情况下,命名空间实际上也没有什么用。不过,在混合使用两种语言的情况下,命名空间的用处就非常大了。
  来看一看下面这个混合了 XHTML 和 SVG 语言的文档:


    
        Example XHTML page
    
    
        
            
        
    

  在上述例子中,通过设置命名空间,将标识为了与包含文档无关的元素。此时,元素的所有子元素,以及这些元素的所有特性,都被认为属于 http://www.w3.org/2000/svg 命名空间。
  即使这个文档从技术上说是一个 XHTML 文档,但因为有了命名空间,其中的 SVG代码也仍然是有效的。
  对于类似这样的文档来说,最有意思的事发生在调用方法操作文档节点的情况下。例如,在创建一个元素时,这个元素属于哪个命名空间呢?在查询一个特殊标签名时,应该将结果包含在哪个命名空间中呢?
  “DOM2 级核心” 通过为大多数 DOM1 级方法提供特定于命名空间的版本解决了这个问题。

1. Node 类型的变化

  在 DOM2 级中,Node 类型包含下列特定于命名空间的属性。

  • localName:不带命名空间前缀的节点名称。
  • namespaceURI:命名空间 URI 或者(在未指定的情况下是)null。
  • prefix:命名空间前缀或者(在未指定的情况下是)null。

  当节点使用了命名空间前缀时,其 nodeName 等于 prefix+":"+ localName。以下面的文档为例:


    
        Example XHTML page
    
    
        
            
        
    

  对于元素来说,它的 localName 和 tagName 是"html",namespaceURI 是 "http://www.w3.org/1999/xhtml",而 prefix 是 null。

  对于元素而言,它的 localName 是"svg",
tagName 是"s:svg",namespaceURI 是"http://www.w3.org/2000/svg",而 prefix 是"s"。

  DOM3 级在此基础上更进一步,又引入了下列与命名空间有关的方法。

  • isDefaultNamespace(namespaceURI):在指定的 namespaceURI 是当前节点的默认命名空间的情况下返回 true。
  • lookupNamespaceURI(prefix):返回给定 prefix 的命名空间。
  • lookupPrefix(namespaceURI):返回给定 namespaceURI 的前缀。

  针对前面的例子,可以执行下列代码:

console.log(document.body.isDefaultNamespace("http://www.w3.org/1999/xhtml"); // true

// 假设 svg 中包含着对的引用
console.log(svg.lookupPrefix("http://www.w3.org/2000/svg")); //"s"
console.log(svg.lookupNamespaceURI("s")); //"http://www.w3.org/2000/svg"

  在取得了一个节点,但不知道该节点与文档其他元素之间关系的情况下,这些方法是很有用的。

2. Document 类型的变化

  DOM2 级中的 Document 类型也发生了变化,包含了下列与命名空间有关的方法。

  • createElementNS(namespaceURI, tagName):使用给定的 tagName 创建一个属于命名空间 namespaceURI 的新元素。
  • createAttributeNS(namespaceURI, attributeName):使用给定的 attributeName 创建一个属于命名空间 namespaceURI 的新特性。
  • getElementsByTagNameNS(namespaceURI, tagName):返回属于命名空间 namespaceURI 的 tagName 元素的 NodeList。

  使用这些方法时需要传入表示命名空间的 URI(而不是命名空间前缀),如下面的例子所示。

// 创建一个新的 SVG 元素
var svg = document.createElementNS("http://www.w3.org/2000/svg","svg");

// 创建一个属于某个命名空间的新特性
var att = document.createAttributeNS("http://www.somewhere.com", "random");

// 取得所有 XHTML 元素
var elems = document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "*");

  只有在文档中存在两个或多个命名空间时,这些与命名空间有关的方法才是必需的。

3. Element 类型的变化

  “DOM2 级核心”中有关 Element 的变化,主要涉及操作特性。新增的方法如下。

  • getAttributeNS(namespaceURI, localName):取得属于命名空间 namespaceURI 且名为 localName 的特性。
  • getAttributeNodeNS(namespaceURI, localName):取得属于命名空间 namespaceURI 且名为 localName 的特性节点。
  • getElementsByTagNameNS(namespaceURI, tagName):返回属于命名空间 namespaceURI 的 tagName 元素的 NodeList。
  • hasAttributeNS(namespaceURI,localName):确定当前元素是否有一个名为 localName 的特性,而且该特性的命名空间是 namespaceURI。注意,“DOM2 级核心”也增加了一个 hasAttribute() 方法,用于不考虑命名空间的情况。
  • removeAttriubteNS(namespaceURI,localName):删除属于命名空间 namespaceURI 且名为 localName 的特性。
  • setAttributeNS(namespaceURI,qualifiedName,value):设置属于命名空间 namespaceURI 且名为 qualifiedName 的特性的值为 value。
  • setAttributeNodeNS(attNode):设置属于命名空间 namespaceURI 的特性节点。

  除了第一个参数之外,这些方法与 DOM1 级中相关方法的作用相同;第一个参数始终都是一个命名空间 URI。

4. NamedNodeMap 类型的变化

  NamedNodeMap 类型也新增了下列与命名空间有关的方法。由于特性是通过 NamedNodeMap 表示的,因此这些方法多数情况下只针对特性使用。

  • getNamedItemNS(namespaceURI, localName):取得属于命名空间 namespaceURI 且名为 localName 的项。
  • removeNamedItemNS(namespaceURI, localName):移除属于命名空间 namespaceURI 且名为 localName 的项。
  • setNamedItemNS(node):添加 node,这个节点已经事先指定了命名空间信息。

  由于一般都是通过元素访问特性,所以这些方法很少使用。

1.2、其他方面的变化

  DOM 的其他部分在“DOM2 级核心”中也发生了一些变化。这些变化与 XML 命名空间无关,而是更倾向于确保 API 的可靠性及完整性。

1. DocumentType 类型的变化

  DocumentType 类型新增了 3 个属性:publicId、systemId 和 internalSubset.

  其中,前两个属性表示的是文档类型声明中的两个信息段,这两个信息段在 DOM1 级中是没有办法访问到的。以下面的 HTML 文档类型声明为例。


  对这个文档类型声明而言,publicId 是"-//W3C//DTD HTML 4.01//EN",而 systemId 是 "http://www.w3.org/TR/html4/strict.dtd"。

  在支持 DOM2 级的浏览器中,应该可以运行下列代码。

console.log(document.doctype.publicId);
console.log(document.doctype.systemId);

  实际上,很少需要在网页中访问此类信息。

  最后一个属性 internalSubset,用于访问包含在文档类型声明中的额外定义,以下面的代码为例。

] >

  访问 document.doctype.internalSubset 将得到 ""

  这种内部子集(internal subset)在 HTML 中极少用到,在 XML 中可能会更常见一些。

2. Document 类型的变化

  Document 类型的变化中唯一与命名空间无关的方法是 importNode()。
  这个方法的用途是从一个文档中取得一个节点,然后将其导入到另一个文档,使其成为这个文档结构的一部分。
  需要注意的是,每个节点都有一个 ownerDocument 属性,表示所属的文档。如果调用 appendChild() 时传入的节点属于不同的文档(ownerDocument 属性的值不一样),则会导致错误。
  但在调用 importNode() 时传入不同文档的节点则会返回一个新节点,这个新节点的所有权归当前文档所有。
  说起来,importNode() 方法与 Element 的 cloneNode() 方法非常相似,它接受两个参数:要复制的节点和一个表示是否复制子节点的布尔值。返回的结果是原来节点的副本,但能够在当前文档中使用。示例:

var newNode = document.importNode(oldNode, true); // 导入节点及其所有子节点
document.body.appendChild(newNode);

  这个方法在 HTML 文档中并不常用,在 XML 文档中用得比较多。

  “DOM2 级视图”模块添加了一个名为 defaultView 的属性,其中保存着一个指针,指向拥有给定文档的窗口(或框架)。
  除此之外,“视图”规范没有提供什么时候其他视图可用的信息,因而这是唯一一个新增的属性。

  除 IE 之外的所有浏览器都支持 defaultView 属性。

  在 IE 中有一个等价的属性名叫 parentWindow(Opera 也支持这个属性)。

  因此,要确定文档的归属窗口,可以使用以下代码。

var parentWindow = document.defaultView || document.parentWindow;

  除了上述一个方法和一个属性之外,“DOM2级核心”还为 document.implementation 对象规定了两个新方法:createDocumentType() 和 createDocument()。
  前者用于创建一个新的 DocumentType 节点,接受 3 个参数:文档类型名称、publicId、systemId。例如,下列代码会创建一个新的 HTML4.01 Strict 文档类型。

var doctype = document.implementation.createDocumentType("html",
                  "-//W3C//DTD HTML 4.01//EN",
                  "http://www.w3.org/TR/html4/strict.dtd");

  由于既有文档的文档类型不能改变,因此 createDocumentType() 只在创建新文档时有用;

  创建新文档时需要用到 createDocument() 方法。这个方法接受 3 个参数:针对文档中元素的 namespaceURI、文档元素的标签名、新文档的文档类型。下面这行代码将会创建一个空的新XML 文档。

var doc = document.implementation.createDocument("", "root", null);

  这行代码会创建一个没有命名空间的新文档,文档元素为,而且没有指定文档类型。

  要想创建一个 XHTML 文档,可以使用以下代码。

var doctype = document.implementation.createDocumentType("html",
                  " -//W3C//DTD XHTML 1.0 Strict//EN",
                  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");

var doc = document.implementation.createDocument("http://www.w3.org/1999/xhtml",
             "html", doctype);

  这样,就创建了一个带有适当命名空间和文档类型的新 XHTML 文档。不过,新文档当前只有文档元素,剩下的所有元素都需要继续添加。

  “DOM2 级 HTML”模块也为 document.implementation 新增了一个方法,名叫 createHTMLDocument()。
  这个方法的用途是创建一个完整的 HTML 文档,包括、、 和 <body>元素。<br>   这个方法只接受一个参数,即新创建文档的标题(放在<title>元素中的字符串),返回新的 HTML 文档,如下所示:</p> <pre><code>var htmldoc = document.implementation.createHTMLDocument("New Doc"); console.log(htmldoc.title); // "New Doc" console.log(typeof htmldoc.body); // "object" </code></pre> <p>  通过调用 createHTMLDocument() 创建的这个文档,是 HTMLDocument 类型的实例,因而具有该类型的所有属性和方法,包括 title 和 body 属性。只有 Opera 和 Safari 支持这个方法。</p> <h5>3. Node 类型的变化</h5> <p>  Node 类型中唯一与命名空间无关的变化,就是添加了 isSupported() 方法。<br>   与 DOM1 级为 document.implementation 引入的 hasFeature() 方法类似,isSupported() 方法用于确定当前节点具有什么能力。<br>   这个方法也接受相同的两个参数:特性名和特性版本号。如果浏览器实现了相应特性,而且能够基于给定节点执行该特性,isSupported() 就返回 true。示例:</p> <pre><code>if (document.body.isSupported("HTML", "2.0")){ // 执行只有"DOM2 级 HTML"才支持的操作 } </code></pre> <p>  由于不同实现在决定对什么特性返回 true 或 false 时并不一致,这个方法同样也存在与 hasFeature() 方法相同的问题。<br>   为此,我们建议在确定某个特性是否可用时,最好还是使用能力检测。</p> <p>  DOM3 级引入了两个辅助比较节点的方法:isSameNode() 和 isEqualNode()。</p> <p>  这两个方法都接受一个节点参数,并在传入节点与引用的节点相同或相等时返回 true。<br>   所谓相同,指的是两个节点引用的是同一个对象。所谓相等,指的是两个节点是相同的类型,具有相等的属性(nodeName、nodeValue,等等),而且它们的 attributes 和 childNodes 属性也相等(相同位置包含相同的值)。示例:</p> <pre><code>var div1 = document.createElement("div"); div1.setAttribute("class", "box"); var div2 = document.createElement("div"); div2.setAttribute("class", "box"); console.log(div1.isSameNode(div1)); // true console.log(div1.isEqualNode(div2)); // true console.log(div1.isSameNode(div2)); // false </code></pre> <p>  这里创建了两个具有相同特性的<div>元素。这两个元素相等,但不相同。</p> <p>  DOM3 级还针对为 DOM 节点添加额外数据引入了新方法。</p> <p>  setUserData() 方法会将数据指定给节点,它接受 3 个参数:要设置的键、实际的数据(可以是任何数据类型)和处理函数。</p> <p>  以下代码可以将数据指定给一个节点。</p> <pre><code>document.body.setUserData("name", "Nicholas", function(){}); </code></pre> <p>  然后,使用 getUserData() 并传入相同的键,就可以取得该数据,如下所示:</p> <pre><code>var value = document.body.getUserData("name"); </code></pre> <p>  传入 setUserData() 中的处理函数会在带有数据的节点被复制、删除、重命名或引入一个文档时调用,因而你可以事先决定在上述操作发生时如何处理用户数据。<br>   处理函数接受 5 个参数:表示操作类型的数值(1 表示复制,2 表示导入,3 表示删除,4 表示重命名)、数据键、数据值、源节点和目标节点。<br>   在删除节点时,源节点是 null;除在复制节点时,目标节点均为 null。<br>   在函数内部,你可以决定如何存储数据。示例:</p> <pre><code>var div = document.createElement("div"); div.setUserData("name", "Nicholas", function(operation, key, value, src, dest){ if (operation == 1){ dest.setUserData(key, value, function(){}); } }); var newDiv = div.cloneNode(true); console.log(newDiv.getUserData("name")); // "Nicholas" </code></pre> <p>  这里,先创建了一个<div>元素,然后又为它添加了一些数据(用户数据)。在使用 cloneNode() 复制这个元素时,就会调用处理函数,从而将数据自动复制到了副本节点。结果在通过副本节点调用 getUserData() 时,就会返回与原始节点中包含的相同的值。</p> <h5>4. 框架的变化</h5> <p>  框架和内嵌框架分别用 HTMLFrameElement 和 HTMLIFrameElement 表示,它们在 DOM2级中都有了一个新属性,名叫 contentDocument。<br>   这个属性包含一个指针,指向表示框架内容的文档对象。在此之前,无法直接通过元素取得这个文档对象(只能使用 frames 集合)。可以像下面这样使用这个属性。</p> <pre><code>var iframe = document.getElementById("myIframe"); var iframeDoc = iframe.contentDocument; // 在 IE8 以前的版本中无效 </code></pre> <p>  由于 contentDocument 属性是 Document 类型的实例,因此可以像使用其他 HTML 文档一样使用它,包括所有属性和方法。Opera、Firefox、Safari 和 Chrome 支持这个属性。<br>   IE8 之前不支持框中的 contentDocument 属性,但支持一个名叫 contentWindow 的属性,该属性返回框架的 window 对象,而这个 window 对象又有一个 document 属性。<br>   因此,要想在上述所有浏览器中访问内嵌框架的文档对象,可以使用下列代码。</p> <pre><code>var iframe = document.getElementById("myIframe"); var iframeDoc = iframe.contentDocument || iframe.contentWindow.document; </code></pre> <p>  所有浏览器都支持 contentWindow 属性。</p> <blockquote> <p>  访问框架或内嵌框架的文档对象要受到跨域安全策略的限制。如果某个框架中的页面来自其他域或不同子域,或者使用了不同的协议,那么要访问这个框架的文档对象就会导致错误。</p> </blockquote> <h3>2、样式</h3> <p>   HTML 中定义样式的方式有 3 种:通过<link/>元素包含外部样式表文件、使用<style/>元素定义嵌入式样式,以及使用 style 特性定义针对特定元素的样式。<br>   “DOM2 级样式”模块围绕这 3 种应用样式的机制提供了一套 API。要确定浏览器是否支持 DOM2 级定义的 CSS 能力,可以使用下列代码。</p> <pre><code>var supportsDOM2CSS = document.implementation.hasFeature("CSS", "2.0"); var supportsDOM2CSS2 = document.implementation.hasFeature("CSS2", "2.0"); </code></pre> <h3>2.1、访问元素的样式</h3> <p>  任何支持 style 特性的 HTML 元素在 JavaScript 中都有一个对应的 style 属性。这个 style 对象是 CSSStyleDeclaration 的实例,包含着通过 HTML 的 style 特性指定的所有样式信息,但不包含与外部样式表或嵌入样式表经层叠而来的样式。<br>   在 style 特性中指定的任何 CSS 属性都将表现为这个 style 对象的相应属性。对于使用短划线(分隔不同的词汇,例如 background-image)的 CSS 属性名,必须将其转换成驼峰大小写形式,才能通过 JavaScript 来访问。下表列出了几个常见的 CSS 属性及其在 style 对象中对应的属性名。</p> <table> <thead> <tr> <th style="text-align:left">CSS属性</th> <th style="text-align:left">JavaScript属性</th> </tr> </thead> <tbody> <tr> <td style="text-align:left">background-image</td> <td style="text-align:left">style.backgroundImage</td> </tr> <tr> <td style="text-align:left">color</td> <td style="text-align:left">style.color</td> </tr> <tr> <td style="text-align:left">display</td> <td style="text-align:left">style.display</td> </tr> <tr> <td style="text-align:left">font-family</td> <td style="text-align:left">style.fontFamily</td> </tr> </tbody> </table> <p>  多数情况下,都可以通过简单地转换属性名的格式来实现转换。其中一个不能直接转换的 CSS 属性就是 float。由于 float 是 JavaScript 中的保留字,因此不能用作属性名。<br>   “DOM2 级样式”规范规定样式对象上相应的属性名应该是 cssFloat;Firefox、Safari、Opera 和 Chrome 都支持这个属性,而 IE<br> 支持的则是 styleFloat。<br>   只要取得一个有效的 DOM 元素的引用,就可以随时使用 JavaScript 为其设置样式。以下是几个例子。</p> <pre><code>var myDiv = document.getElementById("myDiv"); // 设置背景颜色 myDiv.style.backgroundColor = "red"; // 改变大小 myDiv.style.width = "100px"; myDiv.style.height = "200px"; // 指定边框 myDiv.style.border = "1px solid black"; </code></pre> <p>  在以这种方式改变样式时,元素的外观会自动被更新。</p> <blockquote> <p>  在标准模式下,所有度量值都必须指定一个度量单位。<br>   在混杂模式下,可以将 style.width 设置为"20",浏览器会假设它是"20px";<br>   但在标准模式下,将 style.width 设置为"20"会导致被忽略——因为没有度量单位。在实践中,最好始终都指定度量单位。</p> </blockquote> <p>  通过 style 对象同样可以取得在 style 特性中指定的样式。以下面的 HTML 代码为例。</p> <pre><code><div id="myDiv" style="background-color:blue; width:10px; height:25px"></div> </code></pre> <p>  在 style 特性中指定的样式信息可以通过下列代码取得。</p> <pre><code>console.log(myDiv.style.backgroundColor); // "blue" console.log(myDiv.style.width); // "10px" console.log(myDiv.style.height); // "25px" </code></pre> <p>  如果没有为元素设置 style 特性,那么 style 对象中可能会包含一些默认的值,但这些值并不能准确地反映该元素的样式信息。</p> <h5>1. DOM 样式属性和方法</h5> <p>  “DOM2 级样式”规范还为 style 对象定义了一些属性和方法。这些属性和方法在提供元素的 style特性值的同时,也可以修改样式。下面列出了这些属性和方法。</p> <ul> <li>cssText:如前所述,通过它能够访问到 style 特性中的 CSS 代码。</li> <li>length:应用给元素的 CSS 属性的数量。</li> <li>parentRule:表示 CSS 信息的 CSSRule 对象。</li> <li>getPropertyCSSValue(propertyName):返回包含给定属性值的 CSSValue 对象。</li> <li>getPropertyPriority(propertyName):如果给定的属性使用了!important 设置,则返回 "important";否则,返回空字符串。</li> <li>getPropertyValue(propertyName):返回给定属性的字符串值。</li> <li>item(index):返回给定位置的 CSS 属性的名称。</li> <li>removeProperty(propertyName):从样式中删除给定属性。</li> <li>setProperty(propertyName, value, priority):将给定属性设置为相应的值,并加上优先权标志("important"或者一个空字符串)。</li> </ul> <p>  通过cssText 属性可以访问 style特性中的 CSS 代码。<br>   在读取模式下,cssText 返回浏览器对style 特性中 CSS 代码的内部表示。<br>   在写入模式下,赋给 cssText 的值会重写整个 style 特性的值;也就是说,以前通过 style 特性指定的样式信息都将丢失。<br>   例如,如果通过 style 特性为元素设置了边框,然后再以不包含边框的规则重写 cssText,那么就会抹去元素上的边框。下面是使用 cssText 属性的一个例子。</p> <pre><code>myDiv.style.cssText = "width: 25px; height: 100px; background-color: green"; console.log(myDiv.style.cssText); </code></pre> <p>  设置 cssText 是为元素应用多项变化最快捷的方式,因为可以一次性地应用所有变化。</p> <p>  设计 length 属性的目的,就是将其与 item() 方法配套使用,以便迭代在元素中定义的 CSS 属性。<br>   在使用 length 和 item() 时,style 对象实际上就相当于一个集合,都可以使用方括号语法来代替 item() 来取得给定位置的 CSS 属性,如下面的例子所示。</p> <pre><code>for (var i=0, len=myDiv.style.length; i < len; i++){ console.log(myDiv.style[i]); // 或者 myDiv.style.item(i) } </code></pre> <p>  无论是使用方括号语法还是使用 item() 方法,都可以取得 CSS 属性名("background-color",不是"backgroundColor")。然后,就可以在 getPropertyValue() 中使用取得的属性名进一步取得属性的值,如下所示。</p> <pre><code>var prop, value, i, len; for (i=0, len=myDiv.style.length; i < len; i++){ prop = myDiv.style[i]; // 或者 myDiv.style.item(i) value = myDiv.style.getPropertyValue(prop); console.log(prop + " : " + value); } </code></pre> <p>  getPropertyValue() 方法取得的始终都是 CSS 属性值的字符串表示。</p> <p>  如果你需要更多信息,可以使用 getPropertyCSSValue() 方法,它返回一个包含两个属性的 CSSValue 对象,这两个属性分别是:cssText 和 cssValueType。其中,cssText 属性的值与 getPropertyValue()返回的值相同,而 cssValueType 属性则是一个数值常量,表示值的类型:0 表示继承的值,1 表示基本的值,2 表示值列表,3 表示自定义的值。以下代码既输出 CSS 属性值,也输出值的类型。</p> <pre><code>var prop, value, i, len; for (i=0, len=myDiv.style.length; i < len; i++){ prop = myDiv.style[i]; // 或者 myDiv.style.item(i) value = myDiv.style.getPropertyCSSValue(prop); console.log(prop + " : " + value.cssText + " (" + value.cssValueType + ")"); } </code></pre> <p>  在实际开发中,getPropertyCSSValue() 使用得比 getPropertyValue() 少得多。<br>   IE9+、Safarie3+ 以及 Chrome 支持这个方法。Firefox 7 及之前版本也提供这个访问,但调用总返回 null。</p> <p>  要从元素的样式中移除某个 CSS 属性,需要使用 removeProperty() 方法。使用这个方法移除一个属性,意味着将会为该属性应用默认的样式(从其他样式表经层叠而来)。例如,要移除通过 style 特性设置的 border 属性,可以使用下面的代码。</p> <pre><code>myDiv.style.removeProperty("border"); </code></pre> <p>  在不确定某个给定的 CSS 属性拥有什么默认值的情况下,就可以使用这个方法。只要移除相应的属性,就可以为元素应用默认值。</p> <h5>2. 计算的样式</h5> <p>  虽然 style 对象能够提供支持 style 特性的任何元素的样式信息,但它不包含那些从其他样式表层叠而来并影响到当前元素的样式信息。<br>   “DOM2 级样式”增强了 document.defaultView,提供了getComputedStyle() 方法。<br>   这个方法接受两个参数:要取得计算样式的元素和一个伪元素字符串(例如":after")。如果不需要伪元素信息,第二个参数可以是 null。<br>   getComputedStyle()方法返回一个 CSSStyleDeclaration 对象(与 style 属性的类型相同),其中包含当前元素的所有计算的样式。以下面这个 HTML 页面为例。</p> <pre><code><!DOCTYPE html> <html> <head> <title>Computed Styles Example

  应用给这个例子中

元素的样式一方面来自嵌入式样式表(