《Javascript DOM编程艺术》学习笔记 第1-6章

时间:2021-07-23 16:08:11

第1章 Javascript简史

Javascript是Netspace公司与Sun公司合作开发的,Javascript 1.0版于1995年推出。

为与微软公司竞争,Netspace公司和Sun公司联合ECMA制定了Javascript标准,因此Javascript有另一个名字:ECMAScript。

DOM是一套对文档内容进行抽象和概念化的方法。个人理解,就是浏览器把每一个加载的网页视作一个实例化的DOM类型对象,DOM相当于C++/Java中的class类,该class有一些数据成员/字段和成员函数/方法,我们可以通过成员函数/方法来访问和操作这个实例化的DOM对象。

浏览器开发商(Netspace、微软等)在1998年与W3C完成了第一版的DOM通用标准制定(大致可以视作大家统一了成员函数/方法API接口)。

第2章 Javascript语法

Javascript代码通过放在HTML的script标签中来引用,一种是直接内嵌,如下:

<script>
your javascript code
</script>

另外一种是分离风格,如下:

<script src="script_file.js"></script>

Javascript脚本运行不需要在浏览器和操作系统里面安装任何软件或插件。浏览器能够直接识别并解析Javascript脚本,因为现代浏览器都内置有解释引擎(不支持Javascript的浏览器赶紧卸载了)

Javascript语法风格和C系很接近。分号分割语句(可省略),花括号表示语句块。使用和C/C++/Java相同风格的单号注释(//)和多行注释(/* */)

变量声明和上述静态类型语言不同,不需要指定类型,同一变量可以接受不同类型的值。

虽然Javascript声明变量不需要明确指定类型,但是不代表Javascript没有数据类型,其还是存在基本类型。如数值类型、字符串类型、布尔类型。

Javascript中也有数组和对象。Javascript中数组有两种,一种是传统数组,另一种是关联数组,其实是类似于C++/Java中的map数据结构或者Python里面的dict数据结构。

Javascript还有很多的操作符:算术操作符(+, - , *, /, ++, --)、位运算符、赋值运算符、比较运算符、逻辑运算符等。

Javascript也提供条件语句(if)、循环语句(for、while、do while)。

运算符和功能语句基本同C系语言。

Javascript函数的定义使用关键词 function,并且不需要声明返回值(因为Javascript不需要说明变量的类型)。同样地,参数只需参数名,无需参数类型。

Javascript中的变量一样存在作用域,分为全局作用域和局部作用域。

Javascript中的对象也是有数据成员和成员函数的,它们在Javascript中的术语称呼为属性(property)和方法(method)。Javascript的对象通过new关键字来实例化得到。

第3章 DOM

D:表示document,就是表示浏览器加载的那个HTML页面。

O:表示object,就是HTML页面中一个个对象。Javascript中有三种对象:1 用户自定义对象,2 Javascript内置对象,3 浏览器提供的宿主对象

M:表示model,我的理解是结构和关系,也即各个对象间如何组织构成。

节点

浏览器加载得到的HTML页面可以视作一棵树,下面是我从 https://segmentfault.com/a/1190000010721007 抄过来的一个说明图:

《Javascript DOM编程艺术》学习笔记 第1-6章

从上面的图可以看出,一个HTML树有3种类型节点,一种是元素(标签)节点,一种是属性节点,还有一种是一些文本内容,这种是文本节点。但是根据最新的W3C标准,属性已经不再算是节点。

关于文本节点的演示如下:

 <p>
this is a paragraph
<span> some text </span>
<p>

上述代码段中第2行是一个文本节点,它在p元素节点下面,但是第3行中的文本并不是p元素节点的文本节点,因为它被包含在span标签中,它是span标签的文本节点。

获取元素

在DOM中有3种方法可以获取元素,第一种是通过元素的 id 属性标记,第二种是通过 class 属性标记,第三种则是通过标签的名字。

id 属性获取:getElementById(id)  id唯一,因此返回值唯一

class 属性获取:getElementsByClassName(class)  class可重复使用,返回值是数组

标签名获取:getElementsByTagName(tag)  标签可重复使用,返回值是数组,支持通配符"*"查找所有标签。

获取和设置属性(仅支持元素节点,只有元素节点有属性)

属性获取:getAttribue(dst_attr)

属性设置:setAttribue(dst_attr)

第4章 案例研究:Javascript图片库

事件处理函数

事件处理函数的作用是在某个事件发生时调用的函数。

onmouseover事件:鼠标停在某个元素上时可以触发的函数

onmouseout事件:鼠标离开某个元素时可以触发的函数

childNodes属性

访问元素节点的childNodes属性可以获取该元素节点所有子节点(数组形式变量, 仅元素节点支持childNodes )。书本上这里翻译有误,这一小节一直说获取的是子元素,实际不是子元素,是子节点。

nodeType属性

访问节点的nodeType属性可以获取该节点的类型,到底是元素节点,还是文本节点。属性节点已废弃。

nodeValue属性

改变节点的nodeType属性的值,可以改变文件节点的内容。仅文本节点可以改变这个值,元素节点无法更改,因为元素节点没有文本内容,元素节点只包含文本子节点和属性子节点(已废弃的说法)。

第5章 最佳实践

浏览器对Javascript代码要求很严格,一旦遇到错误的Javascript代码,浏览器就不会再执行其后面的代码。

浏览器可能不支持Javascript,但是我认为这种情况基本上没有了。Javascript代码不能执行的一种情况是用户禁用了Javascript支持功能。考虑到这种情况,开发者需要做“平稳退化”。

对于禁用了Javascript支持功能的用户,开发者可能会不在意他有没有禁用而对此感到无所谓,但有种情况:搜索引擎通常不能理解Javascript代码(不支持Javascript)。如果搜索引擎不能很好的理解你的网站,那么会大大影响你的网站排名。

window.popup()函数可以用来弹窗

Javascript伪协议

常见的网络协议有FTP,HTTP,DHCP、TCP、UDP等等,这些协议都是标准通用的。还有一些私有协议是非标准化的,不能被广泛使用的,“Javascript: ”伪协议可以通过一个链接来调用执行Javascript函数。如下:

<a href="javascript:popUp("http://www.example.com");">Example</a>

上面的伪协议的意思是,这是一个Javascript代码,请执行popUp()函数,并且给该函数传入了一个URL字符串参数。

结构与样式分离

类似CSS,Javascript代码不是非得嵌入到HTML代码中,也可以分离出去放在单独的文件中。

对象检测

个人觉得对象检测并没有太大的意义(可能是我还没有多少Javascript代码开发经验),因为我觉得现代浏览器都比较积极快速地支持一些最新的特性(本书之所以在此处和后面强调这些检测,我觉得原因主要是因为这书写作的时间是10年前,那时候浏览器市场还是比较繁杂的)。另外,现有的API支持基本满足了所有需求,所以我在实践中可能不会去写那么多检查代码,那样代码冗余、庞大、低效(这种也算一种浏览器嗅探技术)

尽量减少标记

这么做的理由是能够缩小DOM树的大小,提高搜索效率。

合并、压缩脚本

合并脚本的缘由是把多个文件内容合并,可以减少文件请求次数,因为web服务使用的HTTP是基于TCP的,TCP有握手开销。另外,HTTP规范还限定了浏览器从服务端每次获取文件的并发数。

压缩脚本是另一种有效、常用的优化方式,能显著的缩小文件大小。优化的手段是删除不必要的内容,如空格、注释。还可能重写代码,在逻辑不变的情况下,重命名变量,将其替换为简短的名字,比如

var placeHolder = document.getElementById("placeholder")    //var a=document.getElementById("placeholder")

压缩得到的版本通常命名会有一些提示,比如原本一个someFunction.js压缩后可能会重命名成 someFunction.min.js

第6章 案例研究:图片库改进版

关于onclick事件,为了使Javascript代码和HTML代码分离,使用window.onload事件在页面加载完成后把每个a元素的onclick事件设置为一个匿名函数,需要注意的是,该匿名函数不接受参数,因此不能直接设置onclick=showPic。否则浏览器在检测到点击行为后,虽然调用了showPic( )函数,但是不会传递参数,因此showPic( )函数的参数是undefined,将会在showPic( )函数调用的开头就出错。

window.onload是浏览器提供的一个功能,能够在页面刚加载完成后调用。

nodeName属性能够返回一个元素的标签名字,但是总是返回大写的名字。

这里也介绍了代码优化的很多手段,和第5章后面介绍的对象检测不同,这里是逻辑上保证代码正确,而第5章的检测则是对浏览器支持情况的检测。

实际工作中,我对两种类型的检测都持远离态度:对象检测不需要(浏览器基本都支持),代码逻辑检查没必要(因为HTML代码处于自己的控制范围)

到目前为止,书本介绍的API接口都是标准化的,也存在一些HTML-DOM属性能够简洁代码,比如getElementByTagName("form")可以简写为document.forms、element.getAttribute("src")可以简写为element.src。仔细观察可以发现,一种是通过方法来返回,一种是直接访问属性来操作。