Professional JS(try-catch续/Node/Document类型)

来源:互联网 发布:淘宝店运营商靠谱吗 编辑:程序博客网 时间:2024/05/29 10:36

1.try-catch语句续
①只要代码中包含finally子句,则无论try或catch语句块包含什么代码—-甚至return语句,都不会阻止finally子句的执行。

function testFinally(){    try{        return 0;    }catch(error){        return 1;    }finally{        return 2;    }}testFinally();//2function testFinally(){    try{        return 0;    }catch(error){        return 1;    }}testFinally();//0

②提供提供finally子句,则catch子句就成了可选的(catch和finally有一个即可)。IE7-中有一个BUG:除非有catch子句,否则finally中的代码永远不会被执行。如果需要考虑IE的早期版本,那就只好提供一个catch子句,哪怕里面什么都没有写。IE8修复了这个BUG。

③只要代码中包含了finally子句,那么无论try还是catch语句块中的return语句都会被忽略。

④执行代码期间可能会发生的错误有多种类型。ECMA-262定义了7中错误类型:
a)Error:基类型,其他错误类型都继承自该类型,主要供开发人员抛出自定义错误。
b)EvalError:在使用eval()函数而发生异常时抛出。在实践中,不同的浏览器可能会以其他错误类型替代 EvalError或成功执行。再加上实际开发中极少情况下会使用eval(),因此该错误类型触发的可能性很小。
c)RangeError:在数值超出相应范围时触发。//var a=new Array(-2);
d)ReferenceError:在找不到对象的情况下触发。//var a=b;
e)SyntaxError:将语法错误的JS字符串传入eval()函数时,就会导致此类错误。//eval(‘a+++b’);
e)TypeError:在变量中保存着意外的类型,或在访问不存在的方式时会触发这种错误。归根结底还是由于在执行特定于类型的操作时,变量的类型不符合要求所致。//var a=new 10;
g)URIError:当使用encodeURI()【编码】或decodeURI()【解码】时,URI格式不正确就会触发该错误。

⑤要想知道错误的类型,可以在try-catch语句的catch块中使用instanceof操作符。

try{    someFunction();}catch(error){    if(error instanceof error){        //处理基类型错误    }else if(error instanceof EvalError){        //处理Eval错误    }else if(error instanceof ReferenceError){        //处理引用错误    }else if(error instanceof TypeError){        //处理类型错误    }else if(error instanceof RangeError){        //处理范围错误    }else if(error instanceof SyntaxError){        //处理语法错误    }else if(error instanceof URIError){        //处理URI错误    }else{        //others    }}

⑥try-catch语句适用于处理那些我们无法控制的错误。

2.DOM
①DOM(Document Object Model)是针对HTML和XML文档的一个API(Application Programming interface)

②IE中的所有DOM对象都是以COM对象的形式实现的,这意味着IE中的DOM对象与原生JavaScript对象的行为或活动并不一致。

3.节点层次
①文档元素始终都是html元素。在XML中,没有预定义的元素,因此任何元素都可能成为文档元素。

②JS中所有节点类型都继承自Node类型,因此所有节点类型都共享着相同的基本属性和方法。

③每个节点都有一个nodeType属性,用于表明节点的类型。

//12个数值常量1.Node.ELEMENT_NODE;2.Node.ATTRIBUTE_NODE;//特性3.Node.TEXT_NODE;4.Node.CDATA_SECTION_NODE;//characterData5.Node.ENTITY_REFERENCE_NODE;6.Node.ENTITY_NODE;//实体7.Node.PROCESSING_INSTRUCTION_NODE;8.Node.COMMENT_NODE;9.Node.DOCUMENT_NODE;10.Node.DOCUMENT_TYPE_NODE;11.Node.DOCUMENT_FRAGMENT_NODE;12.Node.NOTATION_NODE;

④为了确保跨浏览器兼容,最好还是将nodeType属性于数字值进行比较。

if(someNode.nodeType==Node.ELEMENT_NODE){ //在IE中无效    alert('Node is an element.');}if(someNode.nodeType==1){   //适用于所有浏览器    alert('Node is an element.'); }

⑤nodeName和nodeValue用于了解节点的具体信息,这两个属性的值完全取决于节点的类型。

⑥对于元素节点,nodeName中保存的始终都是元素的标签名,而nodeValue的值始终为null。

4.节点关系
①每个节点都有一个childNodes属性,其中保存着一个NodeList对象。

②NodeList对象并不是Array的实例,其独特之处在于,它是基于DOM结构动态执行查询的结果,因此DOM结构的变化能够自动反应在NodeList对象中。NodeList是有生命、有呼吸的对象,而不是在我们第一次访问它们的某个瞬间拍摄下来的一张照片。

var firstChild=someNode.childNodes[0];var secondChild=someNode.childNodes.item(1);var count=someNode.childNodes.length;

③对arguments对象使用Array.prototype.slice()方法可以将其转化为数组,采取同样的方法,也可以将NodeList对象转化为数组。

//在IE 8-无效var arrayOfNodes=Array.prototype.slice.call(someNode.childNodes,0);//IE 8-有效---手动枚举所有成员function convertToArray(nodes){    var array=null;    try{        array=Array.prototype.slice.call(nodes,0);//针对非IE浏览器    }catch(ex){        array=new Array();        for(var i=0,len=nodes.lentgh;i<len;i++){            array.push(nodes[i]);        }    }    return array;}

④每个节点都有一个parentNode属性,该属性指向文档树中的父节点。包含在childNodes列表中的每个节点相互之间都是同胞节点,通过使用列表(NodeList)中每个节点的previousSibling和nextSibling属性,可以访问同一列表中的其他节点。

if(someNode.nextSibling===null){    alert("Last node in the parent's childNodes list.");}else if(someNode.previousSibling===null){    alert("First node in the parent's childNodes list.");}

⑤父节点与第一个和最后一个子节点也存在特殊的关系。父节点的firstChild和lastChild属性分别指向其childNodes列表中的第一个和最后一个节点。其中someNode.firstChild的值始终等于someNode.childNodes[0],而someNode.lastChild的值始终等于someNode.childNodes[someNode.childNodes.length-1]。

⑥hasChildNodes()方法在节点包含一或多个子节点的情况下返回true。

⑦所有节点都有的最后一个属性是ownerDocument,该属性指向表示整个文档的文档节点。

⑧虽然所有节点类型都继承自Node,但并不是每种节点都有子节点。

5.操作节点【appendChild()/insertBefore()/replaceChild()/removeChild()】
①最常用的方法是appendChild(),用于向childNodes列表的末尾添加一个节点。添加完节点后,childNodes的新增节点、父节点和以前的最后一个子节点的关系指针都会得到相应的更新。更新完毕后,appendChild()返回新增的节点。

var returnedNode=someNode.appendChild(newNode);//appendChild()方法会返回新增节点alert(returnedNode==newNode);//truealert(someNode.lastChild==newNode);//true

②如果传入到appendChild()中的节点已经是文档的一部分了,那么结果就是将该节点从原来的位置转移到新的位置。

//假设someNode有多个节点var returnedNode=someNode.appendChild(someNode.firstChild);alert(returnedNode==someNode.firstChild);//falsealert(returnedNode==someNode.lastChild);//true

③insertBefore()方法可以将节点放在childNodes列表中某个特定的位置,而不一定是在末尾。该方法接收两个参数:要插入的节点和作为参照的节点。插入节点后,被插入的节点会变成参照节点的前一个同胞节点(previousSibling),同时被方法返回。如果参照节点是null,则insertBefore()与appendChild()执行相同操作。

//insertBefore()方法返回插入的节点//插入后成为最后一个子节点returnedNode=someNode.insertBefore(newNode,null);alert(newNode==someNode.lastChild);//truealert(returnedNode==someNode.lastChild);//true//插入后成为第一个子节点var returnedNode=someNode.insertBefore(newNode,someNode.firstChild);alert(returnedNode==newNode);//truealert(newNode==someNode.firstChild);//true//插入到最后一个子节点的前面returnedNode=someNode.insertBefore(newNode,someNode.lastChild);alert(returnedNode==someNode.childNodes[someNode.childNodes.length-2])//true

④replaceChild()方法接收两个参数:要插入的节点和要替换的节点。要替换的节点通过该方法返回并从文档树中移除,同时由要插入的节点占据位置。

//替换第一个子节点---返回被“覆盖”的子节点,即第一个子节点var returnedNode=someNode.replaceChild(newNode,someNode.firstChild);//替换最后一个子节点---返回被“覆盖”的子节点,即最后一个子节点returnedNode=someNode.replaceChild(newNode,someNode.lastChild);

⑤在使用replaceChild()方法插入一个节点时,该节点的所有关系指针都会从被它替换的节点复制过来。从技术上讲,被替换的节点仍存在于文档中,但已没有了当初的位置。

⑥removeChild()只是移除而非替换节点。该方法只接收一个参数,即为要移除的节点。要移除的节点将成为该方法的返回值。

//移除第一个子节点---返回被移除的第一个子节点var formerFirstChild=someNode.removeChild(someNode.firstChild);//移除最后一个子节点---返回被移除的最后一个子节点var formerLastChild=someNode.removeChild(someNode.lastChild);

6.其他方法
①有两个方法是所有类型的节点共有的。cloneNode()/normalize()

②cloneNode()方法用于创建(调用这个方法)的节点的一个完全相同的副本。cloneNode()方法接收一个布尔值参数,表示是否进行深复制。在参数为true的情况下,执行深复制,也就是复制节点和其整个子节点树;在参数为false的情况下,执行浅复制,即只复制节点本身。复制后返回的节点副本归文档所有,单并没有为其指定父节点。因此,这个节点副本就成为了一个孤儿,除非通过appendChild()、insertBefore()或replaceChild()方法将其添加到文档中。

③cloneNode()方法不会复制(添加到DOM节点中的)JS属性,例如事件处理程序等。这个方法只复制特性、(在明确指定的情况下也复制)子节点,其他一切都不会复制。IE在此存在一个BUG,即它会复制事件处理程序,因此建议在复制之前最好先移除事件处理程序。

④normalize()方法的作用是处理文档树中的文本节点。由于解析器的实现或DOM操作的原因,可能会出现文本节点不包含文本,或接连出现两个文本节点的情况。利用该方法,如果找到空文本节点,则删除它;如果找到相邻的文本节点,则将它们合并为一个文本节点。

7.Document类型
①JS通过Document类型表示文档。在浏览器中,document对象是HTMLDocument(继承自Document类型)的一个实例,表示整个HTML页面。同时,document对象是window对象的一个属性,因此可以将其作为一个全局对象来访问。

②Document节点具有下列特征:
a)nodeType=9;
b)nodeName=’#document’;
c)nodeValue=null;
d)parentNode=null;
e)ownerDocument=null;
f)其子节点可能是一个DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction或Comment。

③最常见的应用是作为HTMLDocument实例的document对象。通过这个文档对象,不仅可以获得与页面有关的信息,而且还能操作页面的外观及其底层结构。

④在FireFox、Safari、Chrome和Opera中,可以通过脚本访问Document类型的构造函数和原型。但在所有浏览器中都可以访问HTMLDocument类型的构造函数和原型,包括IE8+。

8.文档的子节点【document.doctype/注释】
①两个内置的访问其子节点的快捷方式:
a)documentElement属性,该属性始终指向HTML页面中的html元素。
b)通过childNodes列表访问文档元素。

②document.documentElement获得对html的引用。

③document.body获得对body的引用。

④所有浏览器都支持document.documentElement和document.body属性。

⑤document.doctype获得对!doctype的引用

⑥浏览器对document.doctype的支持差别很大:
a)IE 8-:如果存在文档类型声明,会将其错误地解释为一个注释并把它当做Comment节点;而document.doctype的值始终为null。
b)IE 9+及Firefox:如果存在文档类型说明,则将其作为文档的第一个子节点;document.doctype是一个DocumentType节点,也可以通过document.firstChild或document.childNodes[0]访问同一个节点。
c)Safari、Chrome和Opera:如果存在文档类型说明,则将其解析,但不作为文档的子节点。document.doctype是一个DocumentType节点,但该节点不会出现在document.childNodes中。

⑦现实中的浏览器在处理位于外部的注释方面存在如下差异:
这里写图片描述

a)IE 8-、Safari 3.1+、Opera和Chrome只为第一条注释创建节点,不为第二条注释创建节点。导致第一条注释就会成为document.childNodes中的第一个子节点。
b)IE 9+会将第一条注释创建为document.childNodes中的一个注释节点,也会将第二条注释创建为document.childNodes中的注释子节点。
c)Firefox以及Safari 3.1-版本会完全忽略这两个注释。

9.文档信息【title/URL/domain/referrer】
①document对象作为HTMLDocument的一个实例。

②document对象中的title属性,修改title属性会改变元素。

var originalTitle=document.title;document.title='New page title';

③三个与网页的请求相关的属性:URL,domain和referrer

//获取完整的URLvar url=document.URL;//http://www.wrox.com/WileyCDA///获得域名var domain=document.domain;//www.wrox.com//获得来源页面的URLvar referrer=document.referrer;//假设页面来自p2p.worx.com域document.domain='wrox.com';//成功document.domain='nczonline.net';//出错!

a)URL属性中包含着页面完整的URL(即地址栏中显示的URL)。
b)domain属性中只包含页面的域名。
c)referrer属性中保存来源页面的URL。

④由于跨域安全限制,来自不同子域的页面无法通过JS通信。而通过将每个页面的document.domain设置为相同的值,这些页面就可以互相访问对方包含的JS对象了。

⑤浏览器对domain属性还有一个限制,如果域名一开始是”松散的”(loose),那么不能将它再设置为”紧绷的”(tight。)

//假设页面来自于p2p.wrox.com域document.domain='wrox.com';//loosedocument.domain='pwp.wrox.com';//tight
原创粉丝点击