JavaScript 语法和简单用法

 最近看《精通javascript》,作者是jquery之父,相信很多学习javascript的园友也看过这本书,值得研习。看完第五章(the document object model)和第六章(events)感觉还是很受益的,虽然之前对dom和event也算了解,但这次应该说理解更深入了些。

     在遍历Dom中,有个要注意的问题就是,dom中节点的指针(如elem.parentNode, elem.firstChild, elem.nextSibling等)可以指向元素节点,也可以指向文本节点,这里就会造成一定的混乱,比如:<div id="content">

                                                               <p>This is main content area</p>

                                                    </div>

你会怎么定位div中的p元素,可能会想当然的document.getElementById("content").firstChild,遗憾的是得到的是个"/n"(一个文本类型的节点nodeType为3),你要用document.getElementById("content").firstChild.nextSibling才行,这样是不是很麻烦,而且不够简洁和利于阅读。书中封装了一些简单的遍历dom的方法。

function prev(elem) {

  do {

    elem = elem.previousSibling;

  } while(elem && elem.nodeType != 1); // nodeType为1表明节点为元素如:<p>,<a>

      return elem;

}

function next(elem) {

  do {

    elem = elem.nextSibling;

  } while( elem && elem.nodeType != 1);

      return elem;

}

function first(elem) {

  elem = elem.firstChild;

      return elem && elem.nodeType != 1 ?

                 next(elem) : elem;

}

function last(elem) {

  elem = elem.lastChild;

      return elem && elem.nodeType != 1 ?

                 prev(elem) : elem;

}

function parent(elem, num) {

  num = num || 1; //如果num不提供的话,就默认1, 指元素嵌套层数

      for(var i = 0; i < num; i++) {

    if(elem != null ) elem = elem.parentNode;

  }

      return elem;

}

通过这些简单的函数,我们可以像这样遍历dom:first(document.getElementById("content"));这似乎好多了,但是如果让函数的调用换成这种形式应该更符合习惯:document.body.first().next(),我们可以通过扩展HTMLElement达到这样的效果(可惜该死的IE中不能直接访问HTMLElement对象)。

HTMLElement.prototype.next = function() {

  var elem = this;

      do {

    elem = elem.nextSibling;

  } while(elem && elem.nodeType != 1);

      return elem;

}

书中也提到了很常用的getElementByID和getElementsByTagName方法,并提供了简单的封装

function tag(name, elem) {

      //如果elem没提供,那么默认document

  return (elem || document).getElementsByTagName(name);

}

function id(elemId) {

  return document.getElementById(elemId);

}

接下来的一个重点是waiting for the  HTML DOM to load这点很重要,作者也特别说明了下网页加载的顺序:

  1.HTML被浏览器解析

      2.外部的js和css被载入

      3.当在文档中js被解析时,js被执行

      4.HTML DOM构造完成

      5.图片和外部内容被载入

      6.页面加载完成

很显然这里就有个问题,较文档靠前的js或是外部载入的js,如果没等HTML DOM全部构造完,那么这些js对DOM的访问当然会出现问题,作者就此问题给出了几个解决方案。

1.利用window.onload事件,这里为了说明我改了原文中的那addEvent方法(那个复杂些Dean Edwards写的

function addEvent(obj, event, eventHandler) {

  if(obj.addEventListener) { //非IE浏览器 W3C标准

    obj.addEventListener(event, eventHandler, false);  

  } else if (obj.attachEvent) {  //写到这里,我就觉得IE该死。。。

    event = "on" + event;

           obj.attachEvent(event, eventHandler);

  }

}

然后我们可以这样:addEvent(window, "load", function() {

                             first(id("content")).style.background = 'blue';

                         });

这个方法很常用,觉得不错。

2.就是把js的执行代码放到DOM的最后位置

<body>

  <h1>Testing DOM loading</h1>

      <!-- lots of HTML goes here -->

      <script type="text/javascript">init();//这里的init方法已写在<head>中 </script>

</body>

3.这个方法是作者自己写的一个确认dom load结束的一个函数,主要是用来实时监控dom文档的状态,代码如下:

//查看DOM是否已经可以遍历

function isDOMReady() {

  //如果我们已经确认页面加载结束,那么忽略

     if(domReady.done) return false;

     //看看是否一些函数和元素能够被访问

     if(document && document.getElementsByTagName && document.getElementById && document.body) {

    //如果一切就绪,我们停止检查

            clearInterval(domReady.timer);

            domReady.timer = null;

            //执行列队中所有的函数

            for(var i = 0; i < domReady.ready.length; i++) {

        domReady.ready[i]();

            }

            //记住我们现在搞定了

            domReady.ready = null;

            domReady.done = true;

  }

}

function domReady(f) {

  //如果DOM已经加载结束,那么马上执行该函数

      if(domReady.done) return f();

      //如果我们已经添加了一个函数

      if(domReady.timer) {

    //将它加入到执行列表中

    domReady.ready.push(f);

  } else {

    //为页面加载完毕附加一个事件

    addEvent(window, 'load', isDOMReady);

           //初始化执行函数列表

           domReady.ready = [ f ];

           //尽快检查DOM是否加载完毕

           domReady.timer = setInterval(isDOMReady, 13);

  }

}

作者介绍了些找元素的方法,有个Finding Elements by Class Name,实现如下:

function hasClass(name, type) {

  var r = [];

     //定位class name(允许多个class)

      var re = new RegExp("(^|//s)" + name + "(//s|$)");

      var e = document.getElementsByTagName(type || "*");

      for(var j = 0; j < e.length; j++) {

          //如果该元素有该class,那么加入到结果集

     if( re.test(e[j].className) )  r.push(e[j]);

      }

      return r;

}

今天就先到这,明天继续复习.......

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值