标签特性attribute和元素节点属性property
目录
一、区别与联系
二、dom操作标签特性
三、dom操作元素节点属性
四、特性集attributes
一、区别与联系
attribute和property翻译过来都是属性的意思,但二者属于不同的范畴,《JavaScript高级程序设计》将它们翻译为特性和属性以示区分。
attribute是html标签特性,它的值只能是字符串。attribute有固有特性(如id、class等)和自定义特性之分。标签特性保存在attributes特性集中。
property是dom元素节点的属性(元素节点作为对象,浏览器自动为其附加的属性和自定义的属性),它的值可以是任意类型。元素节点是html标签的dom化结果,节点属性的改变会直接同步渲染到标签上。
<div id="d1" jpf="123">100</div>
<script>var div = document.getElementById("d1"); //获取元素节点console.log(div.__proto__); //打印元素节点的属性console.log(div.attributes); //打印attributes特性集
</script>
浏览器会自动将标签固有特性作为属性附加到dom元素节点(只能是固有特性,自定义特性不行)。
<div id="div" jpf="123">100</div>
<script>var div = document.getElementById("div");console.log(div.id); // divconsole.log(div.jpf); //undefined
</script>
value特性和value属性
value特性值是标签的初始value值,除非在JS中刻意编写代码修改,否则自元素出生至销毁value特性值不会改变。value属性值是标签的实时value值。元素刚出生时,value特性值等于value属性值。
元素刚出生并且没有进行任何操作时,直接编写代码修改value特性值,修改结果会同步到value属性,除了这种情况外,value特性和value属性互不影响。value属性值的修改会直接渲染到标签。
<input id="input" value="123" />
<script>var input = document.getElementById("input"); //获取元素节点//------value特性和value属性初始状态时值相等--------------------------------------console.log(input.getAttribute("value")); // 123console.log(input.value); // 123//------value属性修改不影响value特性---------------------------------------------input.value = "789"; console.log(input.getAttribute("value")); // 123console.log(input.value); // 789//------value属性已经修改过的前提下value特性修改不会影响value属性-------------------input.setAttribute("value","456"); console.log(input.getAttribute("value")); // 456console.log(input.value); // 789//------此时input标签的显示值是789-----------------------------------------------
</script>
<input id="input" value="123" />
<script>var input = document.getElementById("input");console.log(input.getAttribute("value")); // 123console.log(input.value); // 123//-------value属性未曾修改过时,value特性的修改会影响value属性-----------input.setAttribute("value","456"); console.log(input.getAttribute("value")); // 456console.log(input.value); // 456
</script>
hidden特性和hidden属性之间互相影响。当标签不设置hidden特性时,hidden特性值默认为null,hidden属性为false,标签显示。当标签设置hidden特性时(单独一个hidden或hidden=xxx),不论特性值是什么,hidden属性值都会编译为true,标签隐藏。同理当hidden属性值为false时,hidden特性值一定是null。
<div id="div">123</div>
<script>var div = document.getElementById("div");console.log(div.getAttribute("hidden")); //nullconsole.log(div.hidden); //false//-----设置hidden特性值,无论特性值是什么,hidden属性值都为true,标签隐藏------div.setAttribute("hidden","");console.log(div.getAttribute("hidden")); //""console.log(div.hidden); //true//-----设置hidden属性为false,标签显示,hidden特性值为null-------------------div.hidden = false;console.log(div.getAttribute("hidden")); //nullconsole.log(div.hidden); //false
</script>
<div id="div1" hidden>123</div>
<div id="div2" hidden="">123</div>
<div id="div3" hidden="false">123</div>
<div id="div4" hidden=null >123</div>
<script>var div1 = document.getElementById("div1");var div2 = document.getElementById("div2");console.log(div1.getAttribute("hidden")); //""console.log(div2.getAttribute("hidden")); //""console.log(div3.getAttribute("hidden")); //"false"console.log(div4.getAttribute("hidden")); //"null"//hedden特性值只要不是null, 其对应的hidden属性值就会编译为true, 标签隐藏
</script>
自定义特性和自定义属性
自定义标签特性和自定义节点属性不会互相影响。
<div id="div" jpf="123"></div>
<script>var div = document.getElementById("div");console.log(div.getAttribute("jpf")); //123console.log(div.jpf); //undefineddiv.lk = "456";console.log(div.getAttribute("lk")); //nullconsole.log(div.lk); //456
</script>
id、class、name
它们的特性和属性无论哪一方发生变化都会互相影响。因为class是ECMA的关键字,所以特性class对应的元素属性是className。className属性值可以包含多个类名,中间用空格隔开。
<div id="div"></div>
<script>var div = document.getElementById("div");console.log(div.getAttribute("id")); //divconsole.log(div.id); //div//-----修改标签的id特性,节点的id属性也会随之变化-------div.setAttribute("id", "fb");console.log(div.getAttribute("id")); //fbconsole.log(div.id); //fb//-----修改节点的id属性,标签的id特性也会随之变化-------div.id = "fb2";console.log(div.getAttribute("id")); //fb2console.log(div.id); //fb2
</script>
style和onclick
style和onclick的特性值是字符串类型,但它们的属性值不是。style的属性值是一个CSSStyleDeclaration对象,里面包含了标签的所有样式信息。onclick的属性值是一个函数。
<div id="n1" style="color:red;" onclick=""></div>
<script>var div = document.getElementById("n1");//-----获取style和onclick特性----------------------------console.log(div.getAttribute("style")); //"color:red;"console.log(div.getAttribute("onclick")); //""//-----获取style和onclick属性----------------------------console.log(div.style);console.log(div.onclick);
</script>
style特性和style属性之间互相影响。
<div id="div">123</div>
<script>var div = document.getElementById("div");//-------style属性影响style特性-------------------------div.style.color = "red"; //文本123变红console.log(div.getAttribute("style")); //"color: red;"//-------style特性影响style属性-------------------------div.setAttribute("style","color: blue;");//文本123变蓝 console.log(div.style.color); //"blue"
</script>
onclick属性不会影响onclick特性,onclick特性会影响onclick属性。
<div id="div">123</div>
<script>var div = document.getElementById("div");//--------onclick属性不会影响onclick特性----------------------------------div.onclick = function(){ //成功为div附件点击事件alert("1");}console.log(div.getAttribute("onclick")); //null//--------onclick特性赋值要注意-------------------------------------------div.setAttribute("onclick","function(){ alert('2')}"); //点击div报语法错误//----------------------------------------------------------------------function func(){alert("2");}div.setAttribute("onclick","func"); //点击div没反应console.log(div.getAttribute("onclick")); //"func"console.log(div.onclick); //ƒ onclick(event){ func }//----------------------------------------------------------------------div.setAttribute("onclick","func()"); //成功为div附件点击事件console.log(div.getAttribute("onclick")); //"func()"console.log(div.onclick); //ƒ onclick(event){ func() }
</script>
二、dom操作标签特性
标签特性dom化后保存在元素节点的attributes特性集中。操作特性的dom方法主要有hasAttribute()、getAttribute()、setAttribute()、removeAttribute()四个,它们都是元素节点的属性,可以针对任何特性使用。元素节点是标签的dom化结果。属性节点是标签特性的dom化结果。属性节点也提供了对标签特性的操作,但用起来没有元素节点提供的这四个方法方便。
hasAttribute()
判断标签是否包含指定特性,返回true或false。ie7及以下版本的浏览器不兼容。
<div id="demo" class="cl1"></div>
<script>console.log(demo.hasAttribute('class')); // trueconsole.log(demo.hasAttribute('title')); // false
</script>
getAttribute()
获取标签特性有两种方法,其一使用getAttribute()方法,其二使用点符号法。标签固有特性和自定义特性都可以用getAttribute()方法获取。使用getAttribute方法,特性不存在或该方法无参数时返回null。getAttribute方法不区分大小写。
<div id="demo" jpf="cl1"></div>
<script>console.log(demo.getAttribute('jpf')); //'cl1'console.log(demo.getAttribute('JPF')); //'cl1'console.log(demo.getAttribute('title')); //nullconsole.log(demo.getAttribute('')); //null
</script>
<div id="n1" name="n2" jpf="n3"></div>
<script>var div = document.getElementById("n1");//----使用getAttribute()方法获取标签特性--------------------console.log(div.getAttribute("name")); //n2 console.log(div.getAttribute("jpf")); //n3//----使用点符号法获取标签特性(特性对象就是属性节点对象)-------------------------------console.log(div.attributes.name.value); //n2 console.log(div.attributes.jpf.value); //n3
</script>
setAttribute()
设置标签固有特性或自定义特性。该方法接收两个参数,其一特性名,其二特性值。要设置的特性如果已经存在,则覆盖原有值。标签特性值必须是字符串类型,如果setAttribute()方法接受了非字符串类型的参数,JavaScript会自动将其转换为字符串类型。setAttribute方法设置特性时,特性名会统一转换成小写形式。
<div id="demo">123</div>
<script>var div = document.getElementById('demo');div.setAttribute("id","test");console.log(div.getAttribute("id")); //test
</script>
<div id="div">123</div>
<script>div.setAttribute("JPF","ceshi"); //div节点变为 <div id="demo" jpf="ceshi">123</div>console.log(div.getAttribute('jpf')); //"ceshi"console.log(div.getAttribute('JPF')); //"ceshi"
</script>
ie7及以下版本的浏览器设置class、style、for、cellspacing、cellpadding、tabindex、readonly、maxlength、rowspan、colspan、usemap、frameborder、contenteditable这13个特性没有任何效果。
<style>.testClass{font-size: 30px;}
</style>
<div id="box">123</div>
<script>//IE7-浏览器下没有任何效果,其他浏览器出现红色背景及30px的文字大小var oBox = document.getElementById('box');oBox.setAttribute("class","testClass");oBox.setAttribute("style","height: 100px; background: red;")
</script>
不推荐使用点符号法为特性赋值。点符号法不能添加新的特性,只能修改已经存在的特性值,且必须直接操作特性对象,不能用新值覆盖掉特性对象。
removeAttribute()
移除标签特性(特性名和特性值都会被删除)。
<div class="demo" id="demo"></div>
<script>var div = document.getElementById('demo');console.log(div.getAttribute("id")); //"demo"div.removeAttribute("id");console.log(div.getAttribute("id")); //null
</script>
三、dom操作元素节点属性
property是元素节点的属性,取值和赋值像一般对象一样操作即可。元素节点的属性可以接收任何类型的属性值。因为class是ECMA的关键字,所以特性class对应的元素属性是className。
<div id="n1" class="n2" name="n3"></div>
<script>var div = document.getElementById("n1");console.log(div.id); //"n1"console.log(div.className); //"n2"console.log(div.name); //undefined, div固有特性中没有name
</script>
以下介绍操作元素节点内容的五个property属性。低版本火狐浏览器不支持innerText和outerText,但随着火狐的更新换代,这两个属性也开始支持。ie8及以下版本的浏览器不支持textContent,在使用innerHTM和outerHTML时,会将所有标签转换成大写形式,且不包含空白文本节点。五个属性中常用的是innerHTML、outerHTML和innerText三个。
innerHTML属性
获取或更新元素节点中的子节点列表。获取操作返回当前元素所有的子节点,返回结果是字符串类型。更新操作能够解析html标签并创建新的子节点,然后用新创建的dom节点完全替换掉当前元素原先的子节点列表。所有浏览器都支持该属性,但ie8及以下版本的浏览器会将innerHTML返回的标签转换为大写形式,且不包含空白文本节点。
<div id="d1"><span>123</span>
</div>
<script>console.log(d1.innerHTML); //"<span>123</span>"
</script>
innerHTML属性设为空(空串或null),会移除当前元素节点的所有子节点。
<div id="d1"><span>123</span>
</div>
<script>d1.innerHTML = ""; //或nullconsole.log(d1.childNodes.length);//0
</script>
在元素上直接设置innerHTML属性的性能高于使用appendChild()方法。但innerHTML属性使用"+="操作符追加内容时,因为该属性既要序列化又要解析,故性能很低,所以一定不要这么使用。
outerHTML属性
获取或更新整个元素节点。与innerHTML相比,它包含当前元素的开始和结束标签。获取操作返回当前元素及其子节点列表。更新操作能够解析html标签并创建新的节点,然后用新创建的dom节点完全替换掉当前元素。所有浏览器都支持该属性,但ie8及以下版本的浏览器会将outerHTML返回的标签转换为大写形式,且不包含空白文本节点。
<div id="d1"><span>1</span>
</div>
<script>console.log(d1.outerHTML); //"<div id='d1'><span>1</span></div>"d1.outerHTML = "<a id='d1'></a>";console.log(d1.outerHTML); //"<a id="d1"></a>"
</script>
<p>123</p>
<script>var p = document.getElementsByTagName('p')[0];//----------用div标签替换掉p标签,此时p标签脱离文档流独立存在------p.outerHTML = "<div>456</div>";console.log(p); //"<p>123</p>"
</script>
outerHTML属性设为空(空串或null),会移除当前元素节点。
<div id="d1"><span id="s1">123</span>
</div>
<script>console.log(d1.childNodes.length);//3s1.outerHTML = ""; //或nullconsole.log(d1.childNodes.length);//1, 还有一个空白文本节点
</script>
textContent属性
textContent属性和innerText属性功能一样,但有两点不同之处,其一适配的浏览器不同,textContent属性在ie8及以下版本的浏览器中不兼容。其二innerText属性属于元素节点,而textContent属性属于所有节点Node。
<p id="p1">This is a <i>simple</i> document</p>
<script>var oText = p1.childNodes[0];console.log(oText.textContent); //'This is a 'console.log(oText.innerText); //undefined
</script>
innerText属性
获取或更新元素子节点树中的文本节点。获取操作会按照由浅入深的顺序,将子节点树中的所有文本节点拼接起来。更新操作会用新的文本节点替换掉元素整个子节点列表。innerText属性操作的是文本节点,它不能解析标签,即使属性值设置成元素节点的样子,最终也只是作为字符串内部的文本显示。
<div>1<span>2</span><span>3</span>
</div>
<script>var div = document.getElementsByTagName("div")[0];var text = div.innerText; //"12 3"div.innerText = "123";console.log(div); //<div>123<div>
</script>
可以将innerText属性设置为其自身以达到去除所有标签的目的。
<div>1<span>2</span><span>3</span>
</div>
<script>var div = document.getElementsByTagName("div")[0];div.innerText = div.innerText;console.log(div); //<div>12 3<div>
</script>
innerText属性和textContent属性功能一样,只是适配的浏览器不同。innerText属性不是w3c标准,不兼容于低版本的狐火浏览器。 innerText和textContent的兼容处理如下。
<div></div>
<script>var div = document.getElementsByTagName("div")[0];function getInnerText(elem) {var bool = typeof(elem.textContent) == "string"return bool ? elem.textContent : elem.innerText;}function setInnerText(elem, text) {if (typeof(elem.textContent) == "string") {elem.textContent = text;} else {elem.innerText = text;}}
</script>
outerText属性
获取操作时,outerText和innerText的结果完全一样。更新操作时,innerText会替换掉当前元素的整个子节点列表,而outerText会替换掉当前整个元素节点。和innerText一样,不兼容于低版本的狐火浏览器。
<div><span id="s1">1</span><span id="s2">2</span>
</div>
<script>var div = document.getElementsByTagName("div")[0];var text = div.outerText; //"1 2"s1.outerText= "123";console.log(div); /*返回结果:<div>123<span id="s2">2</span><div>*/
</script>
四、特性集attributes
attributes是元素节点的属性,用来存储标签特性(固有特性和自定义特性)的dom化结果即属性节点。attributes是一个NamedNodeMap类型的类数组,与NodeList类似,是一个动态集合。下面列举特性集属性中常用的方法。
getNamedItem()
根据名称从特性集中返回指定属性节点。
<div class="box" id="box" name="abc" index="123" title="test"></div>
<script>var div= document.getElementById('box');//NamedNodeMap {0: class, 1: id, 2: name, 3: index, 4: title}console.log(div.attributes);//------使用getNamedItem获取属性节点-----------------------------------console.log(div.attributes.getNamedItem("index")); //index='123'console.log(div.attributes.getNamedItem("index").nodeName); //'index'console.log(div.attributes.getNamedItem("index").nodeValue); //'123'//------使用点符号法获取属性节点----------------------------------------console.log(div.attributes.index);//index='123'console.log(div.attributes.index.nodeName); //'index'console.log(div.attributes.index.nodeValue); //'123'
</script>
removeNamedItem()
根据名称从特性集中移除指定属性节点,并返回被移除的节点。
<div class="box" id="box" name="abc" index="123" title="test"></div>
<script>var div = document.getElementById('box');console.log(div.attributes.getNamedItem("index")); //index='123'console.log(div.attributes.removeNamedItem("index")); //index='123'console.log(div.attributes.getNamedItem("index")); //null
</script>
setNamedItem(node)
向特性集中添加新的属性节点。点符号法不能用来新增属性节点,只能修改已经存在的属性节点,且必须直接操作特性对象即属性节点对象,不能用新值覆盖掉特性对象。
<div class="box" id="box" name="abc" index="123" title="test"></div>
<script>var div = document.getElementById('box');//------移除属性节点----------------------------------------------var node = div.attributes.removeNamedItem("index");console.log(div.attributes.getNamedItem("index")); //nullconsole.log(node); //index='123'//------添加属性节点----------------------------------------------console.log(div.attributes.setNamedItem(node)); //nullconsole.log(div.attributes.getNamedItem("index")); //index='123'
</script>
item(pos)
返回特性集中位于数字pos位置的属性节点,也可以用方括号法[]简写。
<div class="box" id="box" name="abc" index="123" title="test"></div>
<script>var div = document.getElementById('box');//NamedNodeMap {0: class, 1: id, 2: name, 3: index, 4: title}console.log(div.attributes);console.log(div.attributes.item(2)); //name="abc"console.log(div.attributes[2]); //name="abc"
</script>
遍历特性集
<script>function outputAttributes(ele){var pairs = new Array(),attrName,attrValue,i,len;for(i = 0,len=ele.attributes.length;i<len;i++){attrName = ele.attributes[i].nodeName;attrValue = ele.attributes[i].nodeValue;pairs.push(attrName +"='" + attrValue + "'");}return pairs.join(" "); // "id='demo' class='cl1'"}
</script>
遍历时,ie7及以下版本浏览器中没有被设置的特性对应的属性节点也会被返回。可以利用属性节点的specified属性解决这个问题。specified属性值为true表示该属性节点对应的标签特性是被主动设置的。除了ie7及以下版本,其余浏览器中没有被主动设置的标签特性对应的属性节点不会出现在特性集中。ie7及以下版本元素节点的特性集中包含了没有被主动设置的标签对应的属性节点,且节点的specified属性为false。
<div id="box" name="abc" index="123" title="test"></div>
<script>var div = document.getElementById('box');var node1 = div.attributes.getNamedItem("index");var node2 = div.attributes.getNamedItem("onclick");console.log(node1.specified); //所有浏览器浏览器都返回true console.log(node2.specified); //IE7及以下版本返回false。其他浏览器中noNode不存在,报错
</script>
<script>function outputAttributes(ele){var pairs = new Array(),attrName,attrValue,i,len;for(i = 0,len=ele.attributes.length;i<len;i++){attrName = ele.attributes[i].nodeName;attrValue = ele.attributes[i].nodeValue;if(ele.attributes[i].specified){pairs.push(attrName +"='" + attrValue + "'"); }}return pairs.join(" "); // "id='demo' class='cl1'"}
</script>