书香隽秀 - JavaScript
type: channel
link: https://www.huangshuxiu.com/tag/JavaScript/
items: Event 对象
items: 事件模型
items: EventTarget 接口
items: Mutation Observer API
items: CSS 操作
items: Text 节点和 DocumentFragment 节点
items: 属性的操作
items: Element 节点
items: Document 节点
items: ParentNode 接口，ChildNode 接口

Event 对象
type: item
date: 2022-12-19T16:55:37+08:00
description: Event 对象概述事件发生以后，会产生一个事件对象，作为参数传给监听函数。浏览器原生提供一个Event对象，所有的事件都是这个对象的实例，或者说继承了Event.prototype对象。Event对象本身就是一个构造函数，可以用来生成新的实例。event = new Event(type, options);Event构造函数接受两个参数。第一个参数type是字符串，表示事件的名称；第二个参数options是一个对象，表示事件对象的配置。该对象主要有下面两个属性。bubbles：布尔值，可选，默认为false，表示事件对象是否冒泡。cancelable：布尔值，可选，默认为false，表示事件是否可以被取消，即能否用Event.preventDefault()取消这个事件。一旦事件被取消，就好像从来没有发生过，不会触发浏览器对该事件的默认行为。var ev = new Event( 'look', { 'bubbles': true, 'cancelable': false } ); document.dispatchEvent(ev);上面代码新建一个look事件实例，然后使用dispatchEvent方法触发该事件。注意，如果不是显式指定bubbles属性为true，生成的事件就只能在“捕获阶段”触发监听函数。// HTML 代码为 // Hello var div = document.querySelector('div'); var p = document.querySelector('p'); function callback(event) { var tag = event.currentTarget.tagName; console.log('Tag: ' + tag); // 没有任何输出 } div.addEventListener('click', callback, false); var click = new Event('click'); p.dispatchEvent(click);上面代码中，p元素发出一个click事件，该事件默认不会冒泡。div.addEventListener方法指定在冒泡阶段监听，因此监听函数不会触发。如果写成div.addEventListener('click', callback, true)，那么在“捕获阶段”可以监听到这个事件。另一方面，如果这个事件在div元素上触发。div.dispatchEvent(click);那么，不管div元素是在冒泡阶段监听，还是在捕获阶段监听，都会触发监听函数。因为这时div元素是事件的目标，不存在是否冒泡的问题，div元素总是会接收到事件，因此导致监听函数生效。实例属性Event.bubbles，Event.eventPhaseEvent.bubbles属性返回一个布尔值，表示当前事件是否会冒泡。该属性为只读属性，一般用来了解 Event 实例是否可以冒泡。前面说过，除非显式声明，Event构造函数生成的事件，默认是不冒泡的。Event.eventPhase属性返回一个整数常量，表示事件目前所处的阶段。该属性只读。var phase = event.eventPhase;Event.eventPhase的返回值有四种可能。0，事件目前没有发生。1，事件目前处于捕获阶段，即处于从祖先节点向目标节点的传播过程中。2，事件到达目标节点，即Event.target属性指向的那个节点。3，事件处于冒泡阶段，即处于从目标节点向祖先节点的反向传播过程中。Event.cancelable，Event.cancelBubble，event.defaultPreventedEvent.cancelable属性返回一个布尔值，表示事件是否可以取消。该属性为只读属性，一般用来了解 Event 实例的特性。大多数浏览器的原生事件是可以取消的。比如，取消click事件，点击链接将无效。但是除非显式声明，Event构造函数生成的事件，默认是不可以取消的。var evt = new Event('foo'); evt.cancelable // false当Event.cancelable属性为true时，调用Event.preventDefault()就可以取消这个事件，阻止浏览器对该事件的默认行为。如果事件不能取消，调用Event.preventDefault()会没有任何效果。所以使用这个方法之前，最好用Event.cancelable属性判断一下是否可以取消。function preventEvent(event) { if (event.cancelable) { event.preventDefault(); } else { consol…

事件模型
type: item
date: 2022-12-19T14:01:03+08:00
description: 事件模型监听函数浏览器的事件模型，就是通过监听函数（listener）对事件做出反应。事件发生后，浏览器监听到了这个事件，就会执行对应的监听函数。这是事件驱动编程模式（event-driven）的主要编程方式。JavaScript 有三种方法，可以为事件绑定监听函数。HTML 的 on- 属性HTML 语言允许在元素的属性中，直接定义某些事件的监听代码。 上面代码为body节点的load事件、div节点的click事件，指定了监听代码。一旦事件发生，就会执行这段代码。元素的事件监听属性，都是on加上事件名，比如onload就是on + load，表示load事件的监听代码。注意，这些属性的值是将会执行的代码，而不是一个函数。 一旦指定的事件发生，on-属性的值是原样传入 JavaScript 引擎执行。因此如果要执行函数，不要忘记加上一对圆括号。使用这个方法指定的监听代码，只会在冒泡阶段触发。 点击 上面代码中， 是 的子元素。 的click事件，也会触发 的click事件。由于on-属性的监听代码，只在冒泡阶段触发，所以点击结果是先输出1，再输出2，即事件从子元素开始冒泡到父元素。直接设置on-属性，与通过元素节点的setAttribute方法设置on-属性，效果是一样的。el.setAttribute('onclick', 'doSomething()'); // 等同于 // <Element onclick="doSomething()">元素节点的事件属性元素节点对象的事件属性，同样可以指定监听函数。window.onload = doSomething; div.onclick = function (event) { console.log('触发事件'); };使用这个方法指定的监听函数，也是只会在冒泡阶段触发。注意，这种方法与 HTML 的on-属性的差异是，它的值是函数名（doSomething），而不像后者，必须给出完整的监听代码（doSomething()）。EventTarget.addEventListener()所有 DOM 节点实例都有addEventListener方法，用来为该节点定义事件的监听函数。window.addEventListener('load', doSomething, false);addEventListener方法的详细介绍，参见EventTarget章节。小结上面三种方法，第一种“HTML 的 on- 属性”，违反了 HTML 与 JavaScript 代码相分离的原则，将两者写在一起，不利于代码分工，因此不推荐使用。第二种“元素节点的事件属性”的缺点在于，同一个事件只能定义一个监听函数，也就是说，如果定义两次onclick属性，后一次定义会覆盖前一次。因此，也不推荐使用。第三种EventTarget.addEventListener是推荐的指定监听函数的方法。它有如下优点：同一个事件可以添加多个监听函数。能够指定在哪个阶段（捕获阶段还是冒泡阶段）触发监听函数。除了 DOM 节点，其他对象（比如window、XMLHttpRequest等）也有这个接口，它等于是整个 JavaScript 统一的监听函数接口。this 的指向监听函数内部的this指向触发事件的那个元素节点。 点击 执行上面代码，点击后会输出btn。其他两种监听函数的写法，this的指向也是如此。// HTML 代码如下 // 点击 var btn = document.getElementById('btn'); // 写法一 btn.onclick = function () { console.log(this.id); }; // 写法二 btn.addEventListener( 'click', function (e) { console.log(this.id); }, false );上面两种写法，点击按钮以后也是输出btn。事件的传播一个事件发生后，会在子元素和父元素之间传播（propagation）。这种传播分成三个阶段。第一阶段：从window对象传导到目标节点（上层传到底层），称为“捕获阶段”（capture phase）。第二阶段：在目标节点上触发，称为“目标阶段”（target phase）。第三阶段：从目标节点传导回window对象（从底层传回上层），称为“冒泡阶段”（bubbling phase）。这种三阶段的传播模型，使得同一个事件会在多个节点上触发。 点击 上面代码中， 节点之中有一个 节点。如果对这两个节点，都设置click事件的监听函数（每个节点的捕获阶段和冒泡阶段，各设置一个监听函数），共计设置四个监听函数。然后，对 点击，click事件会触发四次。var …

EventTarget 接口
type: item
date: 2022-12-19T13:41:30+08:00
description: EventTarget 接口事件的本质是程序各个组成部分之间的一种通信方式，也是异步编程的一种实现。DOM 支持大量的事件，本章开始介绍 DOM 的事件编程。介绍具体的事件之前，先来看看如何让 DOM 节点监听事件。概述DOM 节点的事件操作（监听和触发），都定义在EventTarget接口。所有节点对象都部署了这个接口，其他一些需要事件通信的浏览器内置对象（比如，XMLHttpRequest、AudioNode、AudioContext）也部署了这个接口。该接口主要提供三个实例方法。addEventListener()：绑定事件的监听函数removeEventListener()：移除事件的监听函数dispatchEvent()：触发事件EventTarget.addEventListener()EventTarget.addEventListener()用于在当前节点或对象上（即部署了 EventTarget 接口的对象），定义一个特定事件的监听函数。一旦这个事件发生，就会执行监听函数。该方法没有返回值。target.addEventListener(type, listener[, useCapture]);该方法接受三个参数。type：事件名称，大小写敏感。listener：监听函数。事件发生时，会调用该监听函数。useCapture：布尔值，如果设为true，表示监听函数将在捕获阶段（capture）触发（参见后文《事件的传播》部分）。该参数可选，默认值为false（监听函数只在冒泡阶段被触发）。下面是一个例子。function hello() { console.log('Hello world'); } var button = document.getElementById('btn'); button.addEventListener('click', hello, false);上面代码中，button节点的addEventListener()方法绑定click事件的监听函数hello()，该函数只在冒泡阶段触发。关于参数，有两个地方需要注意。首先，第二个参数除了监听函数，还可以是一个具有handleEvent方法的对象，效果与监听函数一样。buttonElement.addEventListener('click', { handleEvent: function (event) { console.log('click'); } });上面代码中，addEventListener()方法的第二个参数，就是一个具有handleEvent()方法的对象。其次，第三个参数除了布尔值useCapture，还可以是一个监听器配置对象，定制事件监听行为。该对象有以下属性。capture：布尔值，如果设为true，表示监听函数在捕获阶段触发，默认为false，在冒泡阶段触发。once：布尔值，如果设为true，表示监听函数执行一次就会自动移除，后面将不再监听该事件。该属性默认值为false。passive：布尔值，设为true时，表示禁止监听函数调用preventDefault()方法。如果调用了，浏览器将忽略这个要求，并在控制台输出一条警告。该属性默认值为false。signal：该属性的值为一个 AbortSignal 对象，为监听器设置了一个信号通道，用来在需要时发出信号，移除监听函数。下面是once属性的例子，让监听函数只执行一次。element.addEventListener('click', function (event) { // 只执行一次的代码 }, {once: true});addEventListener()方法可以为针对当前对象的同一个事件，添加多个不同的监听函数。这些函数按照添加顺序触发，即先添加先触发。如果为同一个事件多次添加同一个监听函数，该函数只会执行一次，多余的添加将自动被去除（不必使用removeEventListener()方法手动去除）。function hello() { console.log('Hello world'); } document.addEventListener('click', hello, false); document.addEventListener('click', hello, false);执行上面代码，点击文档只会输出一行Hello world。如果希望向监听函数传递参数，可以用匿名函数包装一下监听函数。function print(x) { console.log(x); } var el = document.getElementById('div1'); el.addEventListener('click', functio…

Mutation Observer API
type: item
date: 2022-12-19T13:18:42+08:00
description: Mutation Observer API概述Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动，比如节点的增减、属性的变动、文本内容的变动，这个 API 都可以得到通知。概念上，它很接近事件，可以理解为 DOM 发生变动就会触发 Mutation Observer 事件。但是，它与事件有一个本质不同：事件是同步触发，也就是说，DOM 的变动立刻会触发相应的事件；Mutation Observer 则是异步触发，DOM 的变动并不会马上触发，而是要等到当前所有 DOM 操作都结束才触发。这样设计是为了应付 DOM 变动频繁的特点。举例来说，如果文档中连续插入1000个 元素，就会连续触发1000个插入事件，执行每个事件的回调函数，这很可能造成浏览器的卡顿；而 Mutation Observer 完全不同，只在1000个段落都插入结束后才会触发，而且只触发一次。Mutation Observer 有以下特点。它等待所有脚本任务完成后，才会运行（即异步触发方式）。它把 DOM 变动记录封装成一个数组进行处理，而不是一条条个别处理 DOM 变动。它既可以观察 DOM 的所有类型变动，也可以指定只观察某一类变动。MutationObserver 构造函数使用时，首先使用MutationObserver构造函数，新建一个观察器实例，同时指定这个实例的回调函数。var observer = new MutationObserver(callback);上面代码中的回调函数，会在每次 DOM 变动后调用。该回调函数接受两个参数，第一个是变动数组，第二个是观察器实例，下面是一个例子。var observer = new MutationObserver(function (mutations, observer) { mutations.forEach(function(mutation) { console.log(mutation); }); });MutationObserver 的实例方法observe()observe()方法用来启动监听，它接受两个参数。第一个参数：所要观察的 DOM 节点第二个参数：一个配置对象，指定所要观察的特定变动var article = document.querySelector('article'); var options = { 'childList': true, 'attributes':true } ; observer.observe(article, options);上面代码中，observe()方法接受两个参数，第一个是所要观察的DOM元素是article，第二个是所要观察的变动类型（子节点变动和属性变动）。观察器所能观察的 DOM 变动类型（即上面代码的options对象），有以下几种。childList：子节点的变动（指新增，删除或者更改）。attributes：属性的变动。characterData：节点内容或节点文本的变动。想要观察哪一种变动类型，就在option对象中指定它的值为true。需要注意的是，至少必须同时指定这三种观察的一种，若均未指定将报错。除了变动类型，options对象还可以设定以下属性：subtree：布尔值，表示是否将该观察器应用于该节点的所有后代节点。attributeOldValue：布尔值，表示观察attributes变动时，是否需要记录变动前的属性值。characterDataOldValue：布尔值，表示观察characterData变动时，是否需要记录变动前的值。attributeFilter：数组，表示需要观察的特定属性（比如['class','src']）。// 开始监听文档根节点（即 标签）的变动 mutationObserver.observe(document.documentElement, { attributes: true, characterData: true, childList: true, subtree: true, attributeOldValue: true, characterDataOldValue: true });对一个节点添加观察器，就像使用addEventListener()方法一样，多次添加同一个观察器是无效的，回调函数依然只会触发一次。如果指定不同的options对象，以后面添加的那个为准，类似覆盖。下面的例子是观察新增的子节点。var insertedNodes = []; var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutati…

CSS 操作
type: item
date: 2022-12-15T15:45:00+08:00
description: CSS 操作CSS 与 JavaScript 是两个有着明确分工的领域，前者负责页面的视觉效果，后者负责与用户的行为互动。但是，它们毕竟同属网页开发的前端，因此不可避免有着交叉和互相配合。本章介绍如何通过 JavaScript 操作 CSS。HTML 元素的 style 属性操作 CSS 样式最简单的方法，就是使用网页元素节点的getAttribute()方法、setAttribute()方法和removeAttribute()方法，直接读写或删除网页元素的style属性。div.setAttribute( 'style', 'background-color:red;' + 'border:1px solid black;' );上面的代码相当于下面的 HTML 代码。 style不仅可以使用字符串读写，它本身还是一个对象，部署了 CSSStyleDeclaration 接口（详见下面的介绍），可以直接读写个别属性。e.style.fontSize = '18px'; e.style.color = 'black';CSSStyleDeclaration 接口简介CSSStyleDeclaration 接口用来操作元素的样式。三个地方部署了这个接口。元素节点的style属性（Element.style）CSSStyle实例的style属性window.getComputedStyle()的返回值CSSStyleDeclaration 接口可以直接读写 CSS 的样式属性，不过，连词号需要变成骆驼拼写法。var divStyle = document.querySelector('div').style; divStyle.backgroundColor = 'red'; divStyle.border = '1px solid black'; divStyle.width = '100px'; divStyle.height = '100px'; divStyle.fontSize = '10em'; divStyle.backgroundColor // red divStyle.border // 1px solid black divStyle.height // 100px divStyle.width // 100px上面代码中，style属性的值是一个 CSSStyleDeclaration 实例。这个对象所包含的属性与 CSS 规则一一对应，但是名字需要改写，比如background-color写成backgroundColor。改写的规则是将横杠从 CSS 属性名中去除，然后将横杠后的第一个字母大写。如果 CSS 属性名是 JavaScript 保留字，则规则名之前需要加上字符串css，比如float写成cssFloat。注意，该对象的属性值都是字符串，设置时必须包括单位，但是不含规则结尾的分号。比如，divStyle.width不能写为100，而要写为100px。另外，Element.style返回的只是行内样式，并不是该元素的全部样式。通过样式表设置的样式，或者从父元素继承的样式，无法通过这个属性得到。元素的全部样式要通过window.getComputedStyle()得到。CSSStyleDeclaration 实例属性（1）CSSStyleDeclaration.cssTextCSSStyleDeclaration.cssText属性用来读写当前规则的所有样式声明文本。var divStyle = document.querySelector('div').style; divStyle.cssText = 'background-color: red;' + 'border: 1px solid black;' + 'height: 100px;' + 'width: 100px;';注意，cssText的属性值不用改写 CSS 属性名。删除一个元素的所有行内样式，最简便的方法就是设置cssText为空字符串。divStyle.cssText = '';（2）CSSStyleDeclaration.lengthCSSStyleDeclaration.length属性返回一个整数值，表示当前规则包含多少条样式声明。// HTML 代码如下 // var myDiv = document.getElementById('myDiv'); var divStyle = myDiv.style; divStyle.length // 3上面代码中，myDiv元素的行内样式共包含3条样式规则。（3）CSSStyleDeclaration.parentRuleCSSStyleDeclaration.paren…

Text 节点和 DocumentFragment 节点
type: item
date: 2022-12-15T14:50:33+08:00
description: Text 节点和 DocumentFragment 节点Text 节点的概念文本节点（Text）代表元素节点（Element）和属性节点（Attribute）的文本内容。如果一个节点只包含一段文本，那么它就有一个文本子节点，代表该节点的文本内容。通常我们使用父节点的firstChild、nextSibling等属性获取文本节点，或者使用Document节点的createTextNode方法创造一个文本节点。// 获取文本节点 var textNode = document.querySelector('p').firstChild; // 创造文本节点 var textNode = document.createTextNode('Hi'); document.querySelector('div').appendChild(textNode);浏览器原生提供一个Text构造函数。它返回一个文本节点实例。它的参数就是该文本节点的文本内容。// 空字符串 var text1 = new Text(); // 非空字符串 var text2 = new Text('This is a text node');注意，由于空格也是一个字符，所以哪怕只有一个空格，也会形成文本节点。比如， 包含一个空格，它的子节点就是一个文本节点。文本节点除了继承Node接口，还继承了CharacterData接口。Node接口的属性和方法请参考《Node 接口》一章，这里不再重复介绍了，以下的属性和方法大部分来自CharacterData接口。Text 节点的属性datadata属性等同于nodeValue属性，用来设置或读取文本节点的内容。// 读取文本内容 document.querySelector('p').firstChild.data // 等同于 document.querySelector('p').firstChild.nodeValue // 设置文本内容 document.querySelector('p').firstChild.data = 'Hello World';wholeTextwholeText属性将当前文本节点与毗邻的文本节点，作为一个整体返回。大多数情况下，wholeText属性的返回值，与data属性和textContent属性相同。但是，某些特殊情况会有差异。举例来说，HTML 代码如下。 A B C 这时，文本节点的wholeText属性和data属性，返回值相同。var el = document.getElementById('para'); el.firstChild.wholeText // "A " el.firstChild.data // "A "但是，一旦移除节点，wholeText属性与data属性就会有差异，因为这时其实 节点下面包含了两个毗邻的文本节点。el.removeChild(para.childNodes[1]); el.firstChild.wholeText // "A C" el.firstChild.data // "A "lengthlength属性返回当前文本节点的文本长度。(new Text('Hello')).length // 5nextElementSibling，previousElementSiblingnextElementSibling属性返回紧跟在当前文本节点后面的那个同级元素节点。如果取不到元素节点，则返回null。// HTML 为 // Hello World var tn = document.querySelector('div').firstChild; tn.nextElementSibling // WorldpreviousElementSibling属性返回当前文本节点前面最近的同级元素节点。如果取不到元素节点，则返回null：。Text 节点的方法appendData()，deleteData()，insertData()，replaceData()，subStringData()以下5个方法都是编辑Text节点文本内容的方法。appendData()：在Text节点尾部追加字符串。deleteData()：删除Text节点内部的子字符串，第一个参数为子字符串开始位置，第二个参数为子字符串长度。insertData()：在Text节点插入字符串，第一个参数为插入位置，第二个参数为插入的子字符串。replaceData()：用于替换文本，第一个参数为替换开始位置，第二个参数为需要被替换掉的长度，第三个参数为新加入的字符串。subStringData()：用于获取子字符串，第一个参数为子字符串在Text节点中的开始位置，第二个参数…

属性的操作
type: item
date: 2022-12-15T13:55:00+08:00
description: 属性的操作HTML 元素包括标签名和若干个键值对，这个键值对就称为“属性”（attribute）。 链接 上面代码中，a元素包括两个属性：id属性和href属性。属性本身是一个对象（Attr对象），但是实际上，这个对象极少使用。一般都是通过元素节点对象（HTMlElement对象）来操作属性。本章介绍如何操作这些属性。Element.attributes 属性元素对象有一个attributes属性，返回一个类似数组的动态对象，成员是该元素标签的所有属性节点对象，属性的实时变化都会反映在这个节点对象上。其他类型的节点对象，虽然也有attributes属性，但返回的都是null，因此可以把这个属性视为元素对象独有的。单个属性可以通过序号引用，也可以通过属性名引用。// HTML 代码如下 // document.body.attributes[0] document.body.attributes.bgcolor document.body.attributes['ONLOAD']注意，上面代码的三种方法，返回的都是属性节点对象，而不是属性值。属性节点对象有name和value属性，对应该属性的属性名和属性值，等同于nodeName属性和nodeValue属性。// HTML代码为 // var n = document.getElementById('mydiv'); n.attributes[0].name // "id" n.attributes[0].nodeName // "id" n.attributes[0].value // "mydiv" n.attributes[0].nodeValue // "mydiv"下面代码可以遍历一个元素节点的所有属性。var para = document.getElementsByTagName('p')[0]; var result = document.getElementById('result'); if (para.hasAttributes()) { var attrs = para.attributes; var output = ''; for(var i = attrs.length - 1; i >= 0; i--) { output += attrs[i].name + '->' + attrs[i].value; } result.textContent = output; } else { result.textContent = 'No attributes to show'; }元素的标准属性HTML 元素的标准属性（即在标准中定义的属性），会自动成为元素节点对象的属性。var a = document.getElementById('test'); a.id // "test" a.href // "http://www.example.com/"上面代码中，a元素标签的属性id和href，自动成为节点对象的属性。这些属性都是可写的。var img = document.getElementById('myImage'); img.src = 'http://www.example.com/image.jpg';上面的写法，会立刻替换掉img对象的src属性，即会显示另外一张图片。这种修改属性的方法，常常用于添加表单的属性。var f = document.forms[0]; f.action = 'submit.php'; f.method = 'POST';上面代码为表单添加提交网址和提交方法。注意，这种用法虽然可以读写属性，但是无法删除属性，delete运算符在这里不会生效。HTML 元素的属性名是大小写不敏感的，但是 JavaScript 对象的属性名是大小写敏感的。转换规则是，转为 JavaScript 属性名时，一律采用小写。如果属性名包括多个单词，则采用骆驼拼写法，即从第二个单词开始，每个单词的首字母采用大写，比如onClick。有些 HTML 属性名是 JavaScript 的保留字，转为 JavaScript 属性时，必须改名。主要是以下两个。for属性改为htmlForclass属性改为className另外，HTML 属性值一般都是字符串，但是 JavaScript 属性会自动转换类型。比如，将字符串true转为布尔值，将onClick的值转为一个函数，将style属性的值转为一个CSSStyleDeclaration对象。因此，可以对这些属性赋予各种类型的值。属性操作的标准方法概述元素节点提供六个方法，用来操作属性。getAttribute()getAttributeNames()setAttribute()hasAttri…

Element 节点
type: item
date: 2022-12-14T15:21:07+08:00
description: Element 节点简介Element节点对象对应网页的 HTML 元素。每一个 HTML 元素，在 DOM 树上都会转化成一个Element节点对象（以下简称元素节点）。元素节点的nodeType属性都是1。var p = document.querySelector('p'); p.nodeName // "P" p.nodeType // 1Element对象继承了Node接口，因此Node的属性和方法在Element对象都存在。此外，不同的 HTML 元素对应的元素节点是不一样的，浏览器使用不同的构造函数，生成不同的元素节点，比如元素的构造函数是HTMLAnchorElement()， 是HTMLButtonElement()。因此，元素节点不是一种对象，而是许多种对象，这些对象除了继承Element对象的属性和方法，还有各自独有的属性和方法。实例属性元素特性的相关属性（1）Element.idElement.id属性返回指定元素的id属性，该属性可读写。// HTML 代码为 var p = document.querySelector('p'); p.id // "foo"注意，id属性的值是大小写敏感，即浏览器能正确识别 和 这两个元素的id属性，但是最好不要这样命名。（2）Element.tagNameElement.tagName属性返回指定元素的大写标签名，与nodeName属性的值相等。// HTML代码为 // Hello var span = document.getElementById('myspan'); span.id // "myspan" span.tagName // "SPAN"（3）Element.dirElement.dir属性用于读写当前元素的文字方向，可能是从左到右（"ltr"），也可能是从右到左（"rtl"）。（4）Element.accessKeyElement.accessKey属性用于读写分配给当前元素的快捷键。// HTML 代码如下 // 点击 var btn = document.getElementById('btn'); btn.accessKey // "h"上面代码中，btn元素的快捷键是h，按下Alt + h就能将焦点转移到它上面。（5）Element.draggableElement.draggable属性返回一个布尔值，表示当前元素是否可拖动。该属性可读写。（6）Element.langElement.lang属性返回当前元素的语言设置。该属性可读写。// HTML 代码如下 // document.documentElement.lang // "en"（7）Element.tabIndexElement.tabIndex属性返回一个整数，表示当前元素在 Tab 键遍历时的顺序。该属性可读写。tabIndex属性值如果是负值（通常是-1），则 Tab 键不会遍历到该元素。如果是正整数，则按照顺序，从小到大遍历。如果两个元素的tabIndex属性的正整数值相同，则按照出现的顺序遍历。遍历完所有tabIndex为正整数的元素以后，再遍历所有tabIndex等于0、或者属性值是非法值、或者没有tabIndex属性的元素，顺序为它们在网页中出现的顺序。（8）Element.titleElement.title属性用来读写当前元素的 HTML 属性title。该属性通常用来指定，鼠标悬浮时弹出的文字提示框。元素状态的相关属性（1）Element.hiddenElement.hidden属性返回一个布尔值，表示当前 HTML 元素的hidden属性的值。该属性可读写，用来控制当前元素是否可见。var btn = document.getElementById('btn'); var mydiv = document.getElementById('mydiv'); btn.addEventListener('click', function () { mydiv.hidden = !mydiv.hidden; }, false);注意，该属性与 CSS 设置是互相独立的。CSS 对当前元素可见性的设置，Element.hidden并不能反映出来。也就是说，这个属性并不能用来判断当前元素的实际可见性。CSS 设置的优先级高于Element.hidden。如果 CSS 指定了该元素不可见（display: none）或可见（visibility: visible），那么Element.hidden并不能改变该元素实际的可见性。换言之，这个属性只在 CSS 没有明确设定当前元素的可见性时才有效。（2）Element.contentEditable，Element.i…

Document 节点
type: item
date: 2022-12-14T10:06:39+08:00
description: Document 节点概述document节点对象代表整个文档，每张网页都有自己的document对象。window.document属性就指向这个对象。只要浏览器开始载入 HTML 文档，该对象就存在了，可以直接使用。document对象有不同的办法可以获取。正常的网页，直接使用document或window.document。iframe框架里面的网页，使用iframe节点的contentDocument属性。Ajax 操作返回的文档，使用XMLHttpRequest对象的responseXML属性。内部节点的ownerDocument属性。document对象继承了EventTarget接口和Node接口，并且混入（mixin）了ParentNode接口。这意味着，这些接口的方法都可以在document对象上调用。除此之外，document对象还有很多自己的属性和方法。属性快捷方式属性以下属性是指向文档内部的某个节点的快捷方式。（1）document.defaultViewdocument.defaultView属性返回document对象所属的window对象。如果当前文档不属于window对象，该属性返回null。document.defaultView === window // true（2）document.doctype对于 HTML 文档来说，document对象一般有两个子节点。第一个子节点是document.doctype，指向<DOCTYPE>节点，即文档类型（Document Type Declaration，简写DTD）节点。HTML 的文档类型节点，一般写成 。如果网页没有声明 DTD，该属性返回null。var doctype = document.doctype; doctype // " " doctype.name // "html"document.firstChild通常就返回这个节点。（3）document.documentElementdocument.documentElement属性返回当前文档的根元素节点（root）。它通常是document节点的第二个子节点，紧跟在document.doctype节点后面。HTML网页的该属性，一般是 节点。（4）document.body，document.headdocument.body属性指向 节点，document.head属性指向 节点。这两个属性总是存在的，如果网页源码里面省略了 或 ，浏览器会自动创建。另外，这两个属性是可写的，如果改写它们的值，相当于移除所有子节点。（5）document.scrollingElementdocument.scrollingElement属性返回文档的滚动元素。也就是说，当文档整体滚动时，到底是哪个元素在滚动。标准模式下，这个属性返回的文档的根元素document.documentElement（即 ）。兼容（quirk）模式下，返回的是 元素，如果该元素不存在，返回null。// 页面滚动到浏览器顶部 document.scrollingElement.scrollTop = 0;（6）document.activeElementdocument.activeElement属性返回获得当前焦点（focus）的 DOM 元素。通常，这个属性返回的是 、 、 等表单元素，如果当前没有焦点元素，返回 元素或null。（7）document.fullscreenElementdocument.fullscreenElement属性返回当前以全屏状态展示的 DOM 元素。如果不是全屏状态，该属性返回null。if (document.fullscreenElement.nodeName == 'VIDEO') { console.log('全屏播放视频'); }上面代码中，通过document.fullscreenElement可以知道 元素有没有处在全屏状态，从而判断用户行为。节点集合属性以下属性返回一个HTMLCollection实例，表示文档内部特定元素的集合。这些集合都是动态的，原节点有任何变化，立刻会反映在集合中。（1）document.linksdocument.links属性返回当前文档所有设定了href属性的及 节点。// 打印文档所有的链接 var links = document.links; for(var i = 0; i < links.length; i++) { console.log(links[i]); }（2）document.formsdocument.forms属性返回所有 表单节点。var selectForm = document.forms[0];上面…

ParentNode 接口，ChildNode 接口
type: item
date: 2022-12-14T09:53:23+08:00
description: ParentNode 接口，ChildNode 接口节点对象除了继承 Node 接口以外，还拥有其他接口。ParentNode接口表示当前节点是一个父节点，提供一些处理子节点的方法。ChildNode接口表示当前节点是一个子节点，提供一些相关方法。ParentNode 接口如果当前节点是父节点，就会混入了（mixin）ParentNode接口。由于只有元素节点（element）、文档节点（document）和文档片段节点（documentFragment）拥有子节点，因此只有这三类节点会拥有ParentNode接口。ParentNode.childrenchildren属性返回一个HTMLCollection实例，成员是当前节点的所有元素子节点。该属性只读。下面是遍历某个节点的所有元素子节点的示例。for (var i = 0; i < el.children.length; i++) { // ... }注意，children属性只包括元素子节点，不包括其他类型的子节点（比如文本子节点）。如果没有元素类型的子节点，返回值HTMLCollection实例的length属性为0。另外，HTMLCollection是动态集合，会实时反映 DOM 的任何变化。ParentNode.firstElementChildfirstElementChild属性返回当前节点的第一个元素子节点。如果没有任何元素子节点，则返回null。document.firstElementChild.nodeName // "HTML"上面代码中，document节点的第一个元素子节点是 。ParentNode.lastElementChildlastElementChild属性返回当前节点的最后一个元素子节点，如果不存在任何元素子节点，则返回null。document.lastElementChild.nodeName // "HTML"上面代码中，document节点的最后一个元素子节点是 （因为document只包含这一个元素子节点）。ParentNode.childElementCountchildElementCount属性返回一个整数，表示当前节点的所有元素子节点的数目。如果不包含任何元素子节点，则返回0。document.body.childElementCount // 13ParentNode.append()，ParentNode.prepend()（1）ParentNode.append()append()方法为当前节点追加一个或多个子节点，位置是最后一个元素子节点的后面。该方法不仅可以添加元素子节点（参数为元素节点），还可以添加文本子节点（参数为字符串）。var parent = document.body; // 添加元素子节点 var p = document.createElement('p'); parent.append(p); // 添加文本子节点 parent.append('Hello'); // 添加多个元素子节点 var p1 = document.createElement('p'); var p2 = document.createElement('p'); parent.append(p1, p2); // 添加元素子节点和文本子节点 var p = document.createElement('p'); parent.append('Hello', p);该方法没有返回值。注意，该方法与Node.prototype.appendChild()方法有三点不同。append()允许字符串作为参数，appendChild()只允许子节点作为参数。append()没有返回值，而appendChild()返回添加的子节点。append()可以添加多个子节点和字符串（即允许多个参数），appendChild()只能添加一个节点（即只允许一个参数）。（2）ParentNode.prepend()prepend()方法为当前节点追加一个或多个子节点，位置是第一个元素子节点的前面。它的用法与append()方法完全一致，也是没有返回值。ChildNode 接口如果一个节点有父节点，那么该节点就拥有了ChildNode接口。ChildNode.remove()remove()方法用于从父节点移除当前节点。el.remove()上面代码在 DOM 里面移除了el节点。ChildNode.before()，ChildNode.after()（1）ChildNode.before()before()方法用于在当前节点的前面，插入一个或多个同级节点。两者拥有相同的父节点。注意，该方法不仅可以插入元素节点，还可以插入文本节点。var …