深刻理解JavaScript系列(23):JavaScript与DOM(上)——也适用于新手

文档对象模型Document Object Model

DOM(Document Object Model,文档对象模型)是一个经过和JavaScript进行内容交互的API。Javascript和DOM通常常常做为一个总体,由于Javascript一般都是用来进行DOM操做和交互的。



主要内容来自:http://net.tutsplus.com/tutorials/javascript-ajax/javascript-and-the-dom-series-lesson-1/

关于DOM,有些知识须要注意:
1. window对象做为全局对象,也就是说你能够经过window来访问全局对象。
 属性在对象下面以变量的形式存放,在页面上建立的全部全局对象都会变成window对象的属性。
方法在对象下面以函数的形式存放,由于左右的函数都存放在window对象下面,因此他们也能够称为方法。

2. DOM为web文档建立带有层级的结果,这些层级是经过node节点组成,这里有几种DOM node类型,最重要的是Element, Text, Document。
 Element节点在页面里展现的是一个元素,因此若是你有段落元素(<p>),你能够经过这个DOM节点来访问。
 Text节点在页面里展现的全部文本相关的元素,因此若是你的段落有文本在里面的话,你能够直接经过DOM的Text节点来访问这个文本
 Document节点表明是整个文档,它是DOM的根节点。

3. 每一个引擎对DOM标准的实现有一些轻微的不一样。例如,Firefox浏览器使用的Gecko引擎有着很好的实现(尽管没有彻底遵照W3C规范),但IE浏览器使用的Trident引擎的实现却不完整并且还有bug,给开发人言带来了不少问题。

若是你正在使用Firefox,我推荐你当即下载Firebug插件,对于你了解DOM结构很是有用。

Web上的JavaScript

Script元素

当你在网站页面上使用JavaScript的时候,须要使用SCRIPT元素:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">  
    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">  
        <head>  
                <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
                <title>JavaScript!</title>  
        </head>  
        <body>        
            <script type="text/javascript">  
            // <![CDATA[  
      
            // ]]>  
            </script>        
        </body>  
    </html>  

上述代码,严格来讲SCRIPT的TYPE属性应该设置为application/javascript,可是因为IE不支持这个,因此平时咱们不得不写成text/javascript或者直接去掉type。另外你也能够看到在SCRIPT元素里的注释行// <![CDATA[ 是用来告诉支持XHTML的浏览器,这里面的代码是字符数据而不是XHTML标签,好比若是你在里面的数据使用了<或>,浏览器就不会再解析成XHTML标签了。

Defer属性

任何在SCRIPT元素里声明的代码在页面加载的时候都会运行,惟一一个例外是给SCRIPT元素加上一个defer属性。defer属性告诉浏览器加载完HTML文档之后再执行JS代码,但这个属性只能在IE下使用。

链接外部脚本

若是你想了解外部脚本,只须要简单地在SCRIPT上使用SRC属性就好了,使用单独的JS文件的好处是能够缓存,并且也不须要担忧CDATA方面的问题:

<script type="text/javascript" src="my-script.js"></script>

JavaScript必备

在咱们继续DOM以前,咱们来复习一下JavaScript的核心必备知识,若是你还不了解,也不要紧,咱们在这一章节将稍微花点时间来回顾一下。

JavaScript有几种数据类型:Number, String, Boolean, Object, Undefined and Null。

单行注释使用双斜杠//,双斜杠后面的全部文字都会被注释掉,多行注意使用/*和*/括住。

Number

在JavaScript里全部的Number都是浮点型的,当声明一个数字变量的时候,记得不要使用任何引号。

// 注:使用var类声明变量
var leftSide = 100;  
var topSide = 50;  
var areaOfRectangle = leftSide * topSide; // = 5000  

String

JavaScript里声明字符串特别简单,和其它语言同样,在JS里使用单引号或双引号均可以。

var firstPart = 'Hello';  
var secondPart = 'World!';  
var allOfIt = firstPart + ' ' + secondPart; // Hello World!  
// +符合是字符链接符。也用于数字相加

Boolean

布尔类型用于条件判断,布尔类型是只有2个值:true和false。任何使用逻辑操做符的比较都会返回布尔值。

5 === (3 + 2); // = true  
// 你也能够将布尔值赋给一个变量
var veryTired = true;
// 这样使用
if (veryTired) {
    // 执行代码 
}   

===也是比较操做符,不只比较数值,还比较类型。

Function

函数是特殊的对象。

// 使用function操做符来声明新函数  
function myFunctionName(arg1, arg2) {
    // 函数代码
}

// 你也能够声明匿名函数 
function (arg1, arg2) {
    // Function code goes here.  
}

// 运行函数很简单,直接在函数名称后面加上小括号就能够了
// 或者也能够带上参数
myFunctionName(); // 无参
myFunctionName('foo', 'bar'); // 有参数

// 也可使用自调用  

(function () {
    // 这里自调用函数
})();

Array

数组也是特殊的对象,它包含了一批值(或对象),访问这些数据的话须要使用数字索引:

// 2种方式声明数组

// 字面量:  
var fruit = ['apple', 'lemon', 'banana'];

// Array构造函数:  
var fruit = new Array('apple', 'lemon', 'banana');

fruit[0]; // 访问第1个项(apple)  
fruit[1]; // 访问第2个项(lemon)  
fruit[2]; // 访问第3个项(banana) 

Object

一个对象是一个key-value的集合,和数组类似,惟一的不一样是你能够为每一个数据定义一个名称。

// 2种类型定义Object对象

// 字面量(大括号)
var profile = {
    name: 'Bob',
    age: 99,
    job: 'Freelance Hitman'
};

// 使用Object构造函数
var profile = new Object();
profile.name = 'Bob';
profile.age = 99;
profile.job = 'Freelance Hitman';  

IF/Else语句

JS里使用最多的语句莫过于条件语句了:

var legalDrinkingAge = 21;  
var yourAge = 29;  
  
if ( yourAge >= legalDrinkingAge ) {   
    alert('You can drink.');  
} else {  
    alert('Sorry, you cannot drink.');  

JavaScript操做符

建议你访问这个页面来查看全部的JS操做符,这里我仅仅给出一些例子:   

// 加减乘除
var someMaths = 2 + 3 + 4 - 10 * 100 / 2;  
      
// 等于  
if ( 2 == (5 - 3 ) { /* 代码 */ } // == 比较是否相等
      
// 不等于 
if ( 2 != (5 - 3 ) { /* 代码 */ }   
      
// 严格等于(推荐) 
2 === 2 // 代替 2 == 2  
2 !== 3 // 代替 2 != 3  
      
// 赋值:  
var numberOfFruit = 9;  
numberOfFruit -= 2; // 等价于 "numberOfFruit = numberOfFruit - 2"  
numberOfFruit += 2; // 等价于 "numberOfFruit = numberOfFruit + 2"   

Loop循环

Loop循环在是遍历数组或者对象的全部成员的时候很是方便,JavaScript里使用最多的是FOR和WHILE语句。

var envatoTutSites = ['NETTUTS', 'PSDTUTS', 'AUDIOTUTS', 'AETUTS', 'VECTORTUTS'];

// WHILE循环
var counter = 0;
var lengthOfArray = envatoTutSites.length;
while (counter < lengthOfArray) {
    alert(envatoTutSites[counter]);
    counter++; // 等价于counter += 1;  
}

// FOR循环
// i只是用于迭代,能够任意取名 
for (var i = 0, length = envatoTutSites.length; i < length; i++) {
    alert(envatoTutSites[i]);
}  

DOM正文

访问DOM节点

咱们来个例子,一个HTML里包含一段文本和一个无序的列表。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">  
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">  
    <head>  
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
            <title>JavaScript!</title>  
    </head>  
    <body>  
  
        <p id="intro">My first paragraph...</p>  
  
        <ul>  
            <li>List item 1</li>  
            <li>List item 1</li>  
            <li>List item 1</li>  
            <li>List item 1</li>  
            <li>List item 1</li>  
        </ul>  
  
        <script type="text/javascript">  
        // <![CDATA[  
  
        // ]]>  
</script>  
  
    </body>  
</html> 

上面例子里,咱们使用getElementById DOM方法来访问p段落,在SCRIPT里添加以下代码:

var introParagraph = document.getElementById('intro');  
// 如今有了该DOM节点,这个DOM节点展现的是该信息段落

变量introParagraph如今已经引用到该DOM节点上了,咱们能够对该节点作不少事情,好比查询内容和属性,或者其它任何操做,甚至能够删除它,克隆它,或者将它移到到DOM树的其它节点上。

文档上的任何内容,咱们均可以使用JavaScript和DOM API来访问,因此相似地,咱们也能够访问上面的无序列表,惟一的问题是该元素没有ID属性,若是ID的话就可使用相同的方式,或者使用以下getElementsByTagName方式:

var allUnorderedLists = document.getElementsByTagName('ul');  
// 'getElementsByTagName'返回的是一个节点集合
// - 和数组有点类似

getElementsByTagName

getElementsByTagName方法返回的是一个节点集合,和数组相似也有length属性,重要的一个特性是他是live的——若是你在该元素里添加一个新的li元素,这个集合就会自动更新,介于他和数组类型,因此能够和访问数组同样的方法来访问,因此从0开始:

// 访问无序列表: [0]索引
var unorderedList = document.getElementsByTagName('ul')[0];

// 获取全部的li集合:  
var allListItems = unorderedList.getElementsByTagName('li');

// 循环遍历
for (var i = 0, length = allListItems.length; i < length; i++) {
    // 弹出该节点的text内容
    alert(allListItems[i].firstChild.data);
} 

如下图例更清晰地展现了DOM获取的知识:



DOM穿梭

“穿梭”这个词主要是用来描述经过DOM查找节点,DOM API提供了大量的节点属性让咱们来往上或者往下查询节点。

全部的节点都有这些属性,都是能够用于访问相关的node节点:
Node.childNodes: 访问一个单元素下全部的直接子节点元素,能够是一个可循环的类数组对象。该节点集合能够保护不一样的类型的子节点(好比text节点或其余元素节点)。
Node.firstChild: 与‘childNodes’数组的第一个项(‘Element.childNodes[0]‘)是一样的效果,仅仅是快捷方式。
Node.lastChild: 与‘childNodes’数组的最后一个项(‘Element.childNodes[Element.childNodes.length-1]‘)是一样的效果,仅仅是快捷方式。shortcut.
Node.parentNode: 访问当前节点的父节点,父节点只能有一个,祖节点能够用‘Node.parentNode.parentNode’的形式来访问。
Node.nextSibling: 访问DOM树上与当前节点同级别的下一个节点。
Node.previousSibling: 访问DOM树上与当前节点同级别的上一个节点。



经过这张图,理解起来就简单多了,但有个很是重要的知识点:那就是元素之间不能有空格,若是ul和li之间有空格的话,就会被认为是内容为空的text node节点,这样ul.childNodes[0]就不是第一个li元素了。相应地,<p>的下一个节点也不是<ul>,由于<p>和<ul>之间有一个空行的节点,通常遇到这种状况须要遍历全部的子节点而后判断nodeType类型,1是元素,2是属性,3是text节点,详细的type类型能够经过此地址:

    Node.ELEMENT_NODE == 1
    Node.ATTRIBUTE_NODE == 2
    Node.TEXT_NODE == 3
    Node.CDATA_SECTION_NODE == 4
    Node.ENTITY_REFERENCE_NODE == 5
    Node.ENTITY_NODE == 6
    Node.PROCESSING_INSTRUCTION_NODE == 7
    Node.COMMENT_NODE == 8
    Node.DOCUMENT_NODE == 9
    Node.DOCUMENT_TYPE_NODE == 10
    Node.DOCUMENT_FRAGMENT_NODE == 11
    Node.NOTATION_NODE == 12

总结

原生的DOM方法和属性足够咱们平常的应用了,本章节咱们只列举了一些例子,下一章节咱们列举更多的例子,还会包括浏览器事件模型。

同步与推荐

本文已同步至目录索引:深刻理解JavaScript系列

深刻理解JavaScript系列文章,包括了原创,翻译,转载等各种型的文章,若是对你有用,请推荐支持一把,给大叔写做的动力。
相关文章
相关标签/搜索