书名:《DOM Scripting Web Design with JavaScript and The Document Object Model》(Second Edition)
译名:《JavaScript DOM编程艺术》(第2版)
著:[英]Jeremy Keith; [加]Jeffrey Sambells
译:杨涛 王建桥 杨晓云等
出版发行:人民邮电出版社
本书算是DOM学习方面的经典之作,早闻其名,我也算是怀着忐忑的心情慢慢读完,废话不多说,跟大家分享一下本书的阅读感受。
感受第1章 JavaScript简史
关于JavaScript的起源,以及网景和微软的浏览器大战,网上已有很多资料,在此不再赘述。
本章给我印象最深的有两方面,一是对DOM的不同定义,搞懂定义也许才能理解DOM
DOM的两种定义:
常规:一套对文档的内容进行抽象和概念化的方法;
W3C的定义:一个与系统平台和编程语言无关的接口,程序和脚本可以通过这个接口动态的访问和修改文档的内容,结构和样式。
DOM的更重要的地方在于,W3C推出的标准化DOM让任何一种程序设计语言对任何一种标记语言编写出来的任何一份文档进行操控(突然想到Ajax和XML)。
另一方面来怀念一下一个已经快消失的宏大而充满痛苦的概念DHTML
DHTML:动态HTML,描述HTML、CSS和JavaScript技术组合的术语,其含义在于:
- 利用HTML把网页标记为各种元素;
- 利用CSS设置元素样式和它们显示的位置;
- 利用JavaScript实时地操纵页面和改变样式。
说其痛苦是在于缺乏统一的标准而操作的各浏览器之间的兼容性问题。
第2章 JavaScript语法本章简要的回顾了一下JavaScript的基本语法,所做笔记大致如下
关于把<script>标签放在那里把<script>标签放在HTML文档的最后,<body>标签之前,能使浏览器更快的加载页面
关于语句(statement)的书写:
如果把多条语句放在同一行,应该用分号来隔开它们; 不在一行可以不用分号,但是推荐使用分号;
关于注释(comment):
何为注释:在代码中写的仅供自己参考而JavaScript解释器会直接忽略的信息;
作用:有效了解代码流程(类似便条);
注释的三种方法:
1、以两个斜线作为一行的开始:
//提醒
//是一件好事
2、另一种方法为斜线加星号
/提醒
是一件好事/
3、、HTML风格的注释,功能跟双斜杠类似(不推荐使用)
<!--这也是一种JavaScript中的注释
关于变量(variable):
赋值(assignment):把值放入变量的操作
赋值方法:
mood = “happy”;
age =33;
JavaScript中,如果某个变量赋值之前并未声明,赋值操作将自动声明该变量,提前声明是一种良好的编程习惯;
声明的方法:
1、声明多个变量:var mood,age;
2、同时赋值:var mood=“happy”,age=33;
变量命名:
1、JavaScript中变量和其它语法元素都是区分字母大小写的;
2、命名原则:允许字母,数字,美元符号和下划线(数字不能是第一个字符,下划线可用于使变量名容易阅读);
3、驼峰格式(camel case)是函数名,方法名和对象属性名命名的首选格式。
字面量(literal):可以直接在JavaScript代码中写出来的数据
数据类型
首先区分一下强类型和弱类型:
- 强类型(strongly typed)语言:明确类型声明的语言;
- 弱类型(weakly typed)语言:不需要进行类型声明的语言,JavaScript为本类;
JavaScript中的几种最重要额数据类型(好像ECMA6规定的是7种):
- 字符串:零个或多个字符构成,必须包在引号(单或者双引号,最好根据字符来选择)里;需要时可运用\转义引号;
- 数值:浮点数(floating-point number);
- 布尔值(boolean):true或false,从某种程度上说,为计算机设计程序就是与布尔值打交道,所有的电子电路只能识别和使用布尔数据;
数组:
一些定义:
- 标量(scalar):任意时刻都只能是一个值,像字符串,数值和布尔值等;
- 数组(array):可以看做是存储一组值的一个变量(集合);
- 元素(element):集合中的某一个值;
- 填充(populating):像数组中添加元素的操作,需给出存放位置(下标)及值:beatles[3]=”George“;
数组声明:
- 使用关键字Array声明:
- 指定长度(length):var beatles=Array(4);
- 不指定长度:var beatles=Array();
- 声明并填充:var beatles = Array("John","paul","George"."Ringo");
- 不声明填充:var beatles =["John","paul","George"."Ringo"];
注意事项:
- 下标从0开始;
- 数组元素可以是布尔值,数值以及字符串的任意一种,可混合填充到同一个数组;
- 数组元素还可以是变量;
- 数组元素还可以是一个其它的数组;
数组分类:
- 传统数组: 填充数组时只给出元素的值,各个元素的下标将被自动创建和刷新;
- 关联数组: 为新元素给出下标时,不必局限于使用数字,可以使用字符串,更具有可读性如lennon["name"]="John",本质上,创建关联数组时,所创建的是Array对象的属性;
对象:
定义:一种非常重要的数据类型,是自包含的数据集合。
属性方法和实例:
- 对象中的数据通过两种方式访问:属性(property)和方法(method);
- 属性是属于某个特定对象的变量;
- 方法是属于某个特定对象才能调用的函数;
- 实例(instance):是对象的具体个体。
- 实例创建:创建实例时使用new关键字;var jeremy =new Person;
创建数组的方法:
var lennon = Object();
lennon.name="John";
lennon.year=1940;
或者使用花括号语法:
``var lennon={name:"Jhon",year:1940};
对象分类:
- 自定义对象:利用JavaScript创建的自己的对象
- 内建对象:JavaScript提供的一系列预先定义好的对象;
- 数组也可以看做是JavaScript的内建对象的一种;常见的还有Data对象;
- 宿主对象(host object):由浏览器提供的预定义对象;常见的有Form,Image,Element,document等
说明:
- 与数组类似,对象也是使用一个名字表示一组值,对象的某个值就是对象的属性;
- 使用点号’.‘来获取属性;
- 属性值可以是任何JavaScript值,包括其它对象;
- 通过属性名称来引用值,大大增加了代码的可读性;
操作(operation):
- 算数操作符(arithmetic operation):+,-,*,/,=,++,--,+=;+号可用于多个字符串的拼接(concatenation),在拼接数字和字符串的时候自动把数字转化为字符串;
- 比较运算符:>,<,>=,<=,==,===,!=,!==;==并不表示严格相等,比如false==“”为真;===表示严格相等
- 逻辑操作符(operand):逻辑与&&,逻辑或||,逻辑非!(取反);逻辑操作符的操作对象是布尔值;
条件语句(conditional statement):
- 做判断, if语句;
- 赋值语句(=)总是判断为真;
循环语句:
- while循环:
- do…while循环:适用于希望循环语句至少执行一次;
- for 循环:可以看成while循环的一种变体,但是循环控制结构更加清晰;常用于数组遍历;
函数(function):
- 定义:允许在你的代码里循环调用的语句;
- 参数:传递给函数的数据;多个参数时用逗号隔开;
- 函数的真正魅力在于,你可以把不同的数据传递给它们,而它们将使用这些数据去完成预定的操作;
- return语句:返回函数所得到的值;
- 函数的真正价值体现在,可以把它当做一种数据类型来使用赋值给一个变量;
变量的作用域:
- 全局变量(global variable):可以在脚本的任何位置使用,包括函数内部;
- 局部变量(local variable):只存在于声明它的函数内部
- 在函数中如果使用var ,那个变量就是被视为一个局部变量,只存在于函数之中,如果没使用var 则是全局变量;
本章开头,作者详细的解释了一下DOM三个字母的具体含义。D是基础,没有文档(document)DOM也就无从谈起;O是对象(Object),JavaScript本身就可以看做是由对象构成的语言,其重要性不言而喻;而M是模型(model),其含义是某种事物的表现形式。具体的说DOM把文档表示成了一颗家谱树(DOM使用parent、child,sibling等记号来表明家庭成员之间的关系。
说完DOM,就不得不说构成文档的基本元素节点(node):
节点的定义:网络中的一个连接点,一个网络就是由一些节点构成的集合。
三种重要的节点:
- 元素节点:可包含其它类型的节点
- 文本节点:内容
- 属性节点:对元素做具体的描述,所有的属性都被元素包含
继承(inheritance):类似于DOM,CSS也把文档的内容视为一棵节点树,节点树上的各个元素将继承其父元素的样式属性。
获取元素:
- 三种获取方法:元素ID,标签名字,以及类名字
- getElementById(),id值必须放在单引号或者双引号中;
- typeof:操作数是一个字符串,数值,函数,布尔值还是对象。
- getElementsByTagName():对应一个对象数组,标签放在单引号或者双引号中
- 通配符必须放在“”里,为“”防止与乘号混淆
- 运用通配符可以快速的得出有多少个子元素
- 可以混合使用getElementById()与getElementsByTagName()得到某个具体id元素下的元素数组,每个值都是一个对象。
- getElementsByClassName():是HTML5 DOM新增的一个方法,通过属性中的类名来访问元素:返回值与getElementsByTagName()类似
- 要指定多个类名,只需要在字符串参数中用空格分隔类名,其顺序不重要;
- 每个节点都是一个对象,有自己的属性和方法;
在说明如何获得节点以后,本章又讨论了获取和设置属性的方法,如下:
- getAttribute():该方法只能通过元素节点对象调用;
- setAttribute():该方法允许我们对属性节点的值做出修改;
值得注意的是这两种方法并不是document对象的方法,只能通过元素节点对象调用;
考虑到DOM的工作模式为:先加载文档的静态内容,再动态刷新,动态刷新不影响文档的静态内容。作者非常推荐动态的创建和使用一些东西,并非常推荐使用
``object.setAttribute(attribute,value):
先创建属性,而后设定它的值,其修改不会表现在源代码里面,这一点在本书后面会很常见。
第4章 案例研究:JavaScript图片库本章作者构建了一个简单的图片画廊来复习前两章的知识,在此不再去赘述作者的代码,只说说自己的收获点以及作者的编程思路:
- 为了减少对站点的请求次数(提高性能),应该把这些.js文件合并到一个文件中;
- 事件处理函数:在特定事件发生时,调用特定的JavaScript代码;
- nodeValue属性:用来得到和设置一个节点的值;
- 包含在<p>元素里的文本是另一个节点,它是<p>元素的第一个子节点;
- firstChild和lastChild属性,子节点的第一个和最后一个元素;
- childNodes属性:可以用来获取任何一个元素的所有子元素,是一个包含这个元素全部子元素的数组;
- onload事件处理函数:函数在页面加载时执行;
- nodeType属性:返回节点的类型;node.nodeType(可用此来验证是否获得了自己想选择的节点)
事件处理函数的工作机制:
以onclick为例:我们给某个链接添加一个onclick事件处理函数,并让这个处理函数所触发的JavaScript代码返回的值是true 或 false,这样一来,当被点击时,如果返回的值是false,则认为没被点击,返回的值是true,则认识被点击了(理解了这个含义以后,我们可以人为的操纵点击是否有反应如点击<a>包含的内容使不弹出新的窗口)。
节点的类型总共有12种可取值,有3种具有实用价值:
- 元素节点的nodeType属性值是1
- 属性节点的nodeType属性值是2
- 文本节点的nodeType属性值是3
下面是我理解的作者的编程思路:
1、构建一个链接图片的清单;
2、解决显示位置问题(在本页插入占位符,设置图片显示的地方);
3、利用JavaScript编程,通过更改占位符的src属性来达到在本页显示图片的效果;
4、编辑函数来获得title属性的值,并显示在图片下面充当描述。
达成目标的过程和目标本身同样重要。不同的代码就算展现相同的效果,其差别也是很大的。
第5章 最佳实践在本章作者提出了一些好的网站应该满足的要求:
1、在使用任何一句JavaScript代码时,都应该想想,对这个网页是否有用;
2、平稳退化(graceful degradation):如果正确使用了JavaScript脚本,可以让访问者在他们的浏览器不支持JavaScript的情况下仍能顺利地浏览你网站。虽然某些功能无法使用,但是最基本的操作仍能顺利完成;
3、渐进加强:用额外的信息层去包裹原始数据;使CSS代码负责提供关于“表示”的信息,JavaScript代码负责提供关于“行为”的信息。
4、分离JavaScript:在HTML文档中使用诸如onclick之类的属性也是一种没有效率又容易引发问题的做法。如果利用像CSS中的class和id属性那样,把JavaScript代码调用行为与HTML文档内容和结构分离,网页就会健壮不少。
5、向后兼容:对象检测:检测浏览器对JavaScript的支持程度。用一个if语句的条件表达式看求值结果是true还是false来采取不同的行动。如在代码前加上if(!getElementById) return false;
6、性能考虑
尽量少访问DOM和尽量减少标记
不管什么时候只要是查询DOM中的某些元素,浏览器就会搜索整个DOM树,从中查找可能匹配的元素。
在多个函数都会取得一组类似元素的情况下,可以考虑重新构建代码,把搜索结果保存在一个全局变量里,或者把一组元素以参数形式传递给函数。
减少标记数量的目的在于,过多的不必要的元素只会增加DOM树的规模。
7、合并和放置脚本:减少请求数量是在性能优化时首先要考虑的; 把所以的<script>标签都放在文档的末尾,</body>标记之前,就可以让页面变得更快。
8、压缩脚本:指的是把脚本文件中的不必要的字节,比如空格和注释,统统删除,从而达到“压缩”文件的目的;多数情况下应该有两个版本,一个是工作副本,可以修改代码并添加注释,另一个是精简副本,用于放在站点上,通常在精简副本的文件名上加上min字样。
减少标记数量的目的在于,过多的不必要的元素只会增加DOM树的规模。
以下是本章提出来的一些让我比较长见识的概念:
1、"javascript”伪协议:真协议让我们在因特网上的计算机之间传输数据包,伪协议是一种非标准化的协议,让我们通过一个链接调用JavaScript函数
2、浏览器嗅探技术(browser sniffung):通过浏览器供应商提供的信息来解决向后兼容的问题。可以通过JavaScript代码检索关于浏览器品牌和版本的信息,这些信息可以改善JavaScript脚本代码的向后兼容性,但是风险非常大。(不准确,浏览器种类多,脚本复杂,出现新版本浏览器需要修改脚本)
3、document对象是window对象的一个属性,当window对象触发onload事件时,document对象已经存在,文档树就会被创建成功。
4、代表性的代码压缩工具:JSMin;YUI Compressor;Closure Compiler;
本章里面的像CSS一样分离JavaScript成为一个行为层,下一章作者通过实例来体现如何达到这一点,确实是让我非常有感触的一点。
第6章 案例研究:图片库改进版本章相当于第5章的拓展内容,就是把第五章提出来的一些要求应用在了之前建立的图片库里面。
关于平稳退化,本程序是支持的,<a>可以跳转到新页面查看图片;关于JavaScript与HTML分离,本程序并不满足,比如说在内部文件中存在onclick事件处理函数,应该放在外部文件中并利用onload引用;关于优化,应该首先检测各个函数是否被浏览器支持(if...return false)。
以下是本章的一些其它要点:
1、结构化程序设计要求函数只有一个入口和出口。但是只要出口集中出现在函数的开头部分就是可以接受的。
2、每个事件处理函数只能绑定一条指令。
3、nodeName属性总是返回一个大写字母的值,即使元素在HTML文档中是小写字母。
4、键盘访问: 最好不要使用onkeypress事件处理函数,onclick事件处理函数已经能满足需要,它对键盘的访问支持相当完美。
5、DOM Core和HTML-DOM
DOM Core:getElemenrById
getElementsByTagName
getAttribute
setAttribute
这些DOM方法是DOM Core的组成部分。它们并不专属于JavaScript,支持DOM的任何一种程序设计语言都可以使用它们,它们的用途也并非仅限于处理网页,它们可以用来处理任何一种标记语言编写出来的文档。
HTML-DOM:类似于document.forms;element.src;
代码通常会更短,但是只能用来处理web文档,不能用来处理其它文档。
本章首先回顾了创建标记的方法:
一些传统方法:
1、document.write :
违背了“行为应该与表现分离”的原则。
MIME类型application/xhtml+xml与document.write不兼容,浏览器呈现这种XHTML时,文档根本不会执行document.write方法。
2、innerHTML :
并不是W3C DOM标准的组成部分,但是现在已经包含到HTML5规范里面中了。(最早出现在微软ie4)
就本属性看来,标记下只有一个字符串,其无细节可言,会永久改变原本的文档。比document.write()方法值得推荐
也是HTML专有属性,不能用于其它标记语言文档。
DOM方法:
1、只要用正确的方法,就可以获取DOM节点树上任何一个节点的细节。
2、改变显示内容,但并不会改变物理内容
3、在浏览器看来,DOM节点才是文档
4、createElement方法:
创建元素节点,只创建会出现一个文档碎片(document fragment),它是游荡在JavaScript世界里的一个孤儿。
但是它已经有nodeType和nodeName属性
appendChild方法
createTextNode方法:创建文本节点
以上三者结合使用来扩展文档树
insertBefore方法
parentElement.insertBefore(newElement,targetElement)
targetElement元素的parentNode属性值就是parentElement;
属性节点和文本节点的子元素不允许是元素节点
DOM没有insertAfter函数,不过可以编写一个
function insertAfter(newElement,targetElement){
var parent=targetElement.parentNode;
if (parent.lastChild==targetElement){
parent.appendChild(newElement);
}else{
parent.insertBefore(newElement,targetElement.nextSibling);
}
}
5、Ajax
使用Ajax可以做到只更新页面中的一小部分,其它内容不用重新加载
Ajax的主要优势是对页面的请求以异步方式发送到服务器。
XMLHttpRequest对象
浏览器脚本与服务器之间的中间人的角色。 JavaScript可以通过这个对象自己发送请求,同时自己处理响应。
问题在于不同浏览器实现XMLHttpRequest对象的方式不太一样。
微软最早在IE5中以ActiveX对象的形式实现了一个名叫XMLHTTP的对象,其它浏览器基于XMLHttpRequest来创建新对象:
该对象最有用的是open方法:用来指定服务器上将要访问的文件,指定请求类型:GET、POST或SEND。
访问服务器发送回来的数据要通过两个属性完成,一个是responseText属性,这个属性用于保存文本字符串形式的数据,另一个属性是responseXML属性,用于保存Content-Type头部中指定为text/xml的数据。
使用Ajax需要注意同源策略:使用XMLHttpRequest对象发送的请求只能访问与其所在的HTML处于同一个域中的数据,不能像其它域发送请求,有些浏览器还会限制Ajax请求使用的协议
异步性:脚本在发送XMLHttpRequest请求之后,仍然会继续执行,不会等待响应返回。
XMLHttpRequest对象实际上非常简单,不过只要发挥一点想象力,就可以达成令人炫目的效果。
6、HIjax
我也是第一次在此听说这个概念,其意思是渐进增强地使用Ajax
构建Ajax网站的最好方法,就是先构建一个常规的网站,然后Hijax它。
本章使用函数充实了文档的内容;
创建了一个“略缩语”列表的函数
遍历文档中的abbr元素——保存abbr元素的title属性——保存每个abbr元素所包含的文本——创建了一个定义列表元素——把每个title属性插入表格;
创建了一个文献来源链接函数:
遍历文档中的blockquote元素——保存blockquote元素的cite属性——找到最末尾的位置——把连接插入末尾;
创建了一个显示快捷键清单的函数:
主要利用了<a>标签里面的accesskey属性;
以下是本章其它的一些我认为很重要的内容:
1、不应该用JavaScript把一些重要的内容添加到网页上,不满足平稳退化的原则。
2、应该从内容开始用标记实现良好的结构,然后逐步的加强这些内容,这一点的重要性在创建函数的过程中显现得非常明显;
3、除了标签之间的内容以外,标签内的属性也包含语义信息。在对内容进行标记时,正确的设置标记属性也是工作的重要组成部分。
4、<abbr>标签和<acronym>的区别:
<abbr>:缩略语,对单词或短语的简写形式的统称;
<acronym>:首字母缩写词;
5、在HTML5中<acronym>标签已被<abbr>标签代替;
6、在IE6和更早的IE版本中,不支持<abbr>标记(浏览器大战埋下的恶果);
7、为了和早期的浏览器保持兼容:应该在诸如<img />,反斜杠之前加一个空格
8、如果存在多个js脚本,要注意调用的先后关系,需要调用其它脚本函数的脚本放在后面;
9、blockquote元素包含一个属性cite。这是一个可选属性
10、在编写DOM脚本时,常会想当然的认为某个节点肯定是一个元素节点,这是一种相当常见的错误。如果没有百分之百的把握,一定要去检查NodeType属性值。有很多DOM方法只能用于元素节点,如果用在文本节点上,就会出错。
11、如果把通配符*作为参数传递给getElementsByTagName方法,它会把所以的元素,不管标签名是什么,一一返回给我们;
12、accesskey属性,用于设定快捷键;
13、JavaScript脚本只应该用来充实文档的内容,要避免使用DOM技术来创建核心内容。
本章讲述了如何使用DOM来操纵CSS,讲述了Style属性,以及如何检索样式和改变样式,笔记如下:
1、三位一体的网页:
结构层 —表示层 —行为层
2、CSS利用伪类走进DOM的领地,DOM也可以设置样式
3、style属性是一个对象;
4、减号和加号之类的操作符是保留字符,不允许用在函数或变量的名字里,同时意味着它们也不能用在方法或属性的名字里。 当你需要引用一个中间带减号的CSS属性时,DOM要求你用驼峰命名法。CSS属性font-family变成DOM属性fontFamily
5、color属性以RGB格式的颜色值返回;
6、在设置CSS font-size属性为em为单位,相应的DOM fontSize属性也将以em为单位;在设置CSS font-size属性为px为单位,相应的DOM fontSize属性也将以px为单位
7、style属性只能返回内嵌样式;来自外部文件的style.css及放在<head>部分的样式不能再用DOM style属性检索出来了;
8、可以用赋值符操作;element.style.property=value;
9、使用DOM脚本设置样式的时机有以下几种:
根据元素在节点树里的位置来设置样式,根据某种条件反复设置某种样式,响应事件;
10、在决定是采用纯粹的CSS来解决,还是利用DOM来设置样式。需要考虑两个因素:
- 这个问题最简单的解决方案是什么
- 那种解决方案会得到更多浏览器的支持
11、通过更改className属性来实现样式的更改;
elem.setAttribute("class:,:intro");
element.className=value;
(以上两种是替换而不是追加)
elem.className +="intro";追加
12、对函数进行抽象: 把一个非常具体的东西改进为一个较为通用的东西的过程叫做抽象化(abstraction),把一些常用函数进行抽象化是非常有好处的;
动画的含义:让元素的位置随着时间而不断地发生变化。
本章主要是定义了一个位置随时间运动的函数,而后把它应用到了一个实际的例子;
本章简要的介绍了什么是HTML5,以及如何使用HTML5,最后对HTML5中一些诸如Canvas,视频,音频和表单等特性进行了介绍,本书关于本章的内容,我并没有做太多笔记,以后跟大家分享我看过的关于HTML5书籍的笔记。
第12章 综合示例本章结合了前面十一章的知识从头开始做了一个简单的网站,对前面的知识做了一个很好的回顾,有本书的童鞋们推荐都跟着做一次,真的收获会很大。
附
本书推荐的三个自己构建的函数:
insertAfter函数:
function insertAfter(newElement,targetElement){
var parent=targetElement.parentNode;
if (parent.lastChild==targetElement){
parent.appendChild(newElement);
}else{
parent.insertBefore(newElement,targetElement.nextSibling);
}
}
加载函数:
addLoadEvent(func){
var oldonload=window.onload;
if(typeof window.onload !=‘function’){
window.onload = func;
}else{
window.onload = function(){
oldonload();
func();
}
}
}
添加类名:
function addClass(element,value){
if (!element.className) {
element.className=value;
}else{
newClassName =element.className;
newClassName+="";
newClassName+=value;
element.className=newClassName;
}
}
后记:
都说一本好书至少应该读三次,本书的要点远远不止这些,以后肯定会重读,到时候再有感悟再给大家分享。
热门评论
就是错别字有点多,,,
很不错。
太赞了,值得收藏!!!!!