堆&栈

堆栈是一个在计算机科学中经常使用的抽象数据类型。堆栈在不同的领域有不同的概念,但也有一定的相通性。栈使用的是一级缓存,他们通常都是被调用时处于存储空间中,调用完毕立即释放。堆则是存放在耳机缓存中,声明周期由虚拟机的垃圾回收算法来决定,所以调用这些对象的速度相对栈来说,要慢一些。
形象来说,栈就是一条流水线,而流水线中加工的就是方法的主要程序,在分配栈时,由于程序是自上而下顺序执行,就将程序指令一条一条压入栈中,就像流水线一样。而堆上站着的就是工作人员,他们加工流水线中的商品,由程序员分配:何时加工,如何加工。而我们通常使用new运算符为对象在堆上分配内存(C#,Java),堆上寻找对象的任务交给句柄,而栈中由栈指针管理。

数据结构中的栈

栈:是限定仅在表尾(栈顶top)进行插入或删除操作的线性表。因此栈又称为后进先出(last in first out)的线性表。与线性表类似,栈也有两种存储表示方法:顺序栈、栈的链式表示。栈还有一个重要应用是在程序设计语言中实现递归,即一个直接调用自己活通过一系列的调用语句间接地调用自己的函数,称为递归函数。
队列:和栈相反,是一种先进先出(first in first out)的线性表。

操作系统的堆栈

栈:由操作系统自动分配释放,存放函数的参数值、局部变量的值等。操作方式类似于数据结构中的栈。
堆:一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收,分配方式类似于链表。

C/C++中的堆栈

一个由c/c++编译的程序占用的内存分为以下几个部分

  1. 栈区:由编译器自动分配释放,存放函数的参数名,局部变量名等。其操作方式类似于数据结构中的栈。栈是有最大空间的,超出和报异常提示栈溢出。速度快,但无法控制。
  2. 堆区:由程序员分配释放,若程序员不释放,程序结构时可能由OS回收。它与数据结构中的堆是两回事,分配方式类似于链表。速度慢,但用起来方便(在c中使用malloc获取,在c++中使用new运算符获取)
  3. 静态区:全局变量和局部静态变量的存储放在一块的。程序结束后由系统释放。
  4. 文字常量区:常量字符串放在这里,程序结束后由系统释放。
  5. 程序代码区:存放函数体的二进制代码。

JAVA中的堆栈

栈:除string外的基本数据类型变量都会保存在栈中
堆:使用new来新建对象的,都会在堆中创建。
与C++不同,Java自动管理栈和堆,程序员不能直接设置。栈比堆的存取速度快,仅次于直接位于CPU的寄存器。但栈的数据大小与生存期必须是确定的,缺乏灵活性。栈内部多个值相等的变量是可以指向一个地址的。堆则可以动态分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。
Java中的数据类型分为基本类型和包装类数据。假设编译器处理int a=3;首先,在栈中创建一个变量为a的内存空间,然后查找字面值为3的地址,没有则开辟存放3这个字面值的地址。如果下次给啊赋值4,它又会再去找指向4的地址。这是字面值的引用,而不是类对象的引用。

可维护性、性能及部署

可维护性

可维护的代码一般遵循以下特点

  • 可理解性:其他人可以接受代码并理解它的意图和一般途径
  • 直观性:代码中的东西一看就能明白,而不管其操作过程多么复杂
  • 可适应性:代码以一种数据上的变换不要求完全重写的方法撰写
  • 可扩展性:在damageSumarry结构上已经考虑到在未来允许对核心功能进行扩展
  • 可调试性:当有地方出错时,代码可以给予你足够的信息来尽可能直接地确定问题所在

代码约定

由于JavaScript的可适应性,代码约定对它也很重要。由于和大多数面向对象语言不通,JavaScript并不强制开发人员将所有东西都定义为对象。

  • 可读性:一部分和代码缩进相关。一部分是注释。比如要在函数和方法、大段代码、复杂的算法和Hack处进行注释。
  • 变量和函数命名:变量名应该是名词。函数名应该以动词开始。变量和函数都应使用合乎逻辑的名字,长度问题可以通过后处理和压缩来缓解。一般第一个词为小写,以后的词都是大写。
  • 变量类型透明:一种是定义的时候初始化,则知道它是什么类型。一种是在变量名前加一个标记,比如bFound(布尔型)、iCount(整数)。最后一种是使用类型注释。

松解耦合

只要应用的某个部分过于依赖另一部分,代码就是耦合过紧,难于维护。典型的问题如:对象直接引用另一个对象,并且修改其中一个的同时需要修改另外一个。显示问题的唯一来源应该是CSS,行为问题的唯一来源应该是JavaScript。

  • 解耦HTML/JavaScript:HTML是数据,JavaScript是行为。当JavaScript用于插入数据时,尽量不要直接插入标记。一般可以在页面中直接包含并隐藏标记,然后等到整个页面渲染好之后,就可以用JavaScript显示该编辑,而非生成它。更改行为只需要在JavaScript中进行,而更改标记则只要在渲染文件中。
  • 解耦CSS/JavaScript:要更改样式时,不应该直接更改属性,应该更改元素的类名,达到改变样式的目的,可实现CSS对JavaScript的松散耦合。还要避免在CSS中使用表达式。
  • 解耦应用逻辑/事件处理程序:这两者分别处理各自的东西,一个事件处理程序应该从事件对象中提取相关信息,并将这些信息传送到处理应用逻辑的某个方法中。不能讲event对象传给其他方法,只传来自event对象所需的数据;任何可以在应用层面的动作都应该可以再不执行任何事件处理程序的情况下进行;任何事件处理程序都应该处理事件,然后将处理转交给应用逻辑。

其他

  • 尊重对象所有权。不修改不属于自己的对象。
  • 避免全局变量。最多创建一个全局变量,让其他对象和函数都存在其中。
  • 避免与null进行比较,容易出错。而应该使用instanceof、typeof等。
  • 使用常量。关键在于将数据和使用它的逻辑进行分离。

性能

注意作用域

随着作用域链中的作用域数量的增加,访问当前作用域以外的变量的时间也在增加。访问全局变量总是比访问局部变量蛮,因为需要遍历作用域链。只要能减少花费在作用域链上的时间,就能增加脚本的整体性能。总的来说,就是使用局部变量代替全局变量,减少全局变量使用次数。

1
2
3
4
5
6
7
8
9
10
function updateUI(){  //要避免全局查找
var doc = document; //将document对象存在本地的doc变量中,所以只有一次全局查找
var imgs = doc.getElementByTagName("img");
for(var i=0,len=imgs.length;i < len; i++){
imgs[i].title = doc.title + "image" + i;
}
var msg = doc.getElementById("msg");
msg.innerHTML = "update complete";
}
//此外,还要避免with语句。因为with语句会创建自己的作用域。

选择正确的方法

在计算机科学中,算法的复杂度使用O符号来表示。要选择最简单、最快捷的算法。使用变量和数组要比访问对象上的属性更有效率,前者是O(1),后者为O(n)。所以,属性查找越多,执行时间越长。

对于循环来说,如果循环的次数是确定的,消除循环并使用多次函数调用往往更快。

性能优化过程中很重要的一部分还有优化循环。一个循环的基本优化步骤如下:

  • 减值迭代:在很多情况下,从最大值(特定值)开始,在循环中不断减值的迭代器更加高效
  • 简化终止条件:由于每次循环都要计算终止条件,所以要避免属性查找和其他复杂度高的操作。
  • 简化循环体:确保没有某些可以被很容易移除循环的密集计算。
  • 使用后测试循环:使用do-while这种后测试循环,可以避免最初终止条件的计算。
1
2
3
4
var query = window.location.href.substring(window.location.href.indexof("?)); //6次属性查找

var url = window.location.href;
var query = url.substring(url.indexof("?")); //4次属性查找

最小化语句数

多个变量声明可以写成一个语句。在插入迭代值的时候,尽可能合并语句。尽量使用字面量而不是构造函数来创建数组和对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var count = 5,
color = "blue",
now = new Date(); //合并变量声明语句

var name = values[i++]; //插入迭代值时,合并语句

var person = {
name:"liming",
age:20
}; //应该使用这种字面量的方式创建对象或数组

var person = new Object(); //这种方式不好。这种问题要重点关注
person.name = "liming";
person.age = 20;

优化DOM交互

在JavaScript各个方面中,DOM毫无疑问是最慢的一部分。DOM操作与交互要消耗大量时间。

最小化现场更新

一旦需要访问的DOM部分是已经显示的页面的额一部分,那么就是在进行一个现场更新。每一个修改,都有一个性能惩罚,因为浏览器要重新计算无数尺寸已进行更新。所以要进行减少现场更新次数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var list = document.getElementById("myList"),
fragment = document.createDocumentFragment(),
item,
i;

for(i=0;i<10;i++){
item = document.createElement("li");
fragment.appendChild(item);
item.appendChild(document.createTextNode("Item" + i));
}

list.appendChild(fragment); //只有一次现场更新,而不是10次。

//方法2 使用innerHTML,速度更快
for(i=0;i<10;i++){
html += "<li>Item" +i+ "</li>";
}
list.innerHTML = html;

使用innerHTML

对于小的DOM更改而言,使用createElement()和appendChild(),以及innerTHML来说效率差不多。然而,对于大的DOM更改,使用innerHTML要比使用标准的DOM方法创建同样的DOM结构快得多。当把innerHTML设置为某个值时,后台会创建一个HTML解析器,然后使用内部的DOM调用来创建DOM结构,而非基于JavaScript的DOM调用。由于内部方法是编译好的而非解释执行的,所以执行快得多。

使用事件代理

大多数Web应用在用户交互上大量用到事件处理程序。页面上的时间处理程序的数量和页面相应用户交互的速度之间负相关。为了减轻这种惩罚,最好使用事件代理。

注意HTMLCollection

HTMLCollection对于Web应用的性能而言是巨大的损害。也许优化HTMLCollection访问最重要的地方就是循环了。编写JavaScript的时候,一定要知道何时返回HTMLCollection对象,这样你就可以最小化对他们的访问。发生以下情况时会返回HTMLCollection对象:

  • 进行了对getElementsByTagName()的调用;
  • 获取了元素的childNodes属性;
  • 获取了元素的attributes属性;
  • 访问了特殊的集合,如document.forms、document.images等。

其他

避免解析包含了JavaScript代码的字符串,因为要解析字符串还需要再启动一个解析器,这就是JavaScript代码想解析JavaScript的时候的双重解释乘法。所以要避免出现需要按照JavaScript解释的字符串,比如eval("alert('hello')");
原生方法比较快,所以尽量使用原生方法。因为原生方法是用诸如c/c++之类的编译型语言写出来的。

switch语句较快,如果有一系列复杂的if-else语句,可以转换成单给switch语句。

位运算符比较快,比如取模、逻辑与和逻辑或都可以考虑用位运算来替换。

离线应用于客户端存储

支持离线Web应用开发是HTML5的另一个重点。开发离线Web应用需要几个步骤。首先要确保知道设备是否能上网。然后,应用还必须能访问一定的资源。最后,必须有一块本地空间用于保存数据,无论能否上网都不妨碍读写。

离线检测

HTML5定义了一个navigator.online属性,true表示能上网,false表示设备离线。以下是检测属性状态的示例。

1
2
3
4
5
if(navigator.online){
//正常工作
}else {
//执行离线状态时的任务
}

此外,HTML5还定义了两个事件:onlin和offline。分别在网络离线变在线和在线变离线时触发。

应用缓存

HTML5的应用缓存可以简称为appcache,是专门为开发离线Web应用而设计的。Appcache是从浏览器的缓存中分出来的一块缓存区。可以使用一个描述文件,列出要下载和缓存的资源,就可以将相应的资源存储到这个区域。
要将描述文件与页面关联起来,可以在< html >中的manifest属性中指定这个描述文件的路径。

数据存储

随着Web应用程序的出现,也产生了对于能够直接在客户端上存储用户信息能力的要求。一下为几种客户端存储数据的方式。

HTTP Cookie,最初是在客户端用于存储会话信息的。由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份,所以可以使用cookie作为身份标识,服务器就能确认用户身份了。该标准要求服务器对任意HTTP请求发送Set-Cookie HTTP头最为相应的一部分,其中包含会话信息。
cookie有访问者限制,有长度限制,每个域的cookie总数也有限制。cookie由浏览器保存到额以下几块信息构成:名称、值、域、路径、失效时间、安全标志等。
在JavaScript中处理cookie有些复杂,因为其蹩脚的接口,即BOM的document.cookie属性。这个属性的独特之处在于它会因为使用它的方式不同而表现不同的行为。基本的cookie操作有三种:读取、写入和删除。

Session机制

除了使用Cookie,Web应用程序中还经常使用Session来记录客户端状态。Session是服务器端使用的一种记录客户端状态的机制,使用上比Cookie简单一些,相应的也增加了服务器的存储压力。Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。

IE用户数据

在IE5.0中,微软通过一个自定义行为引入了持久化用户数据的概念。要使用持久化用户数据,就必须使用CSS在某个元素上指定userData行为,该元素即可使用setAttribute()方法在上面保存数据了。为了将数据提交到浏览器缓存中,还必须调用save()方法并告诉它要保存到的数据空间的名字。如下:

1
2
3
4
5
6
7
<div style="behavior:url(#default#userData)" id="dataStore"></div>

dataStore = setAttribute("name","liming");
dataStore = setAttribute("sex","men");
dataStore.save("staffInfo"); //存储

dataStore1.load("staffInfo"); //调用,加载。staffInfo的信息就会加载到dataStore1中

Web存储机制(更大容量存储)

Web Storage成为了HTML5的一部分。其目的是克服由cookie带来的一些限制,当数据需要被严格控制在客户端上时,无须持续地将数据发回服务器。其目标有:提供一种在cookie之外存储会话数据的路径,提供一种存储大量可以跨会话存在的数据的机制。

  • Storage类型提供最大的存储空间来存储名值对儿,但只能存储字符串。Storage的实例有以下方法:clear()、getItem(name)、key(index)、removeItem(name)、setItem(name,value),此外还有length等属性。
  • sessionStorage对象。非持久存储,用于存储特定于某个会话的数据,也就是该数据只保持到浏览器关闭。
  • globalStorage对象。其目的是跨越会话存储数据,但有特定的访问限制。要使用它,首先指定哪些域可以访问该数据,可以通过方括号来标记使用属性来实现。globalStorage的每个属性都是Storage的实例。
1
2
globalStorage["www.wrox.com"].name="Nicholas";
var name = globalStorage["www.wrox.com"].name; //取数据

它会一直保存在磁盘上,所以非常适合在客户端存储文档或者长期保持用户票号设置。

  • localStorage对象
    localStorage对象在修订过的HTML5规范中作为持久保存客户端数据的方案取代了globalStorage。
1
2
3
4
localStorage.setItem("name","liming"); //使用方法存储数据
var name = localStorage.getItem("name");
localStorage.age=22; //使用属性存储数据
var age=localStorage.age;
  • storage事件。对Storage对象进行任何修改,都会在文档上触发storage事件。该event事件有这几个属性:domain(发生变化的存储空间的域名)、key(设置或删除的键名)、newValue、oldValue。

IndexedDB

Indexed Database API,是在浏览器中保存结构化数据的一种数据库。其思想是创建一套API,方便保存和读取JavaScript对象,同时还支持查询及搜索。IndexedDB设计的操作完全是异步进行的。因此,大多数操作会以请求方式进行,但这些操作会在后期执行。差不多每次IndexedDB操作,都需要注册onerror或onsuccess事件处理程序,以确保适当地处理结果。
它是一种类似SQL数据的结构haunted数据存储机制,但它的数据不是保存在表中,而是保存在对象存储空间中。创建对象存储空间时,需要定义一个键,然后就可以添加数据。可以使用游标在对象存储空间中查询特定的对象。而索引则是为了提高查询速度而基于特定的属性创建的。

cookie作为HTTP协议的一部分用来处理客户端和服务器通信是不可或缺的,WebStorage的意图在于解决本来不应该cookie做,却不得不用cookie的本地存储。共同点:保存在浏览器用户端,且都是同源的。(golbalStorage可以不同源)

  • 网络负担:cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
  • 存储大小限制不同:cookie有大小和数目的限制,sessionStorage和localStorage属于Web Storage,则用于更大容量的存储,如chrome每个来源限制为2.5M。
  • 安全性:HTTP请求中的cookie是明文传递的(https不是),WebStorage并不作为HTTP header发送的浏览器,所以相对安全。
  • 使用方便:cookie需要前端开发者自己封装setCookie,getCookie,而Web Storage则拥有setItem、getItem等方法。
  • 数据有效期:cookie有失效时间。sessionStorage用于非持久存储,用于存储会话数据,浏览器关闭即销毁。localStorage用于持久存储,访问时,页面也localStorage必须来自同一个域名。
  • 作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。
  • Web Storage 支持事件通知机制,可以将数据更新的通知发送给监听者。Web Storage 的 api 接口使用更方便。

Ajax与JSON

JSON

JSON是一种数据格式,而不是一种编程语言。JSON并不从属于JavaScript,并不是只有JavaScript才可以用JSON,但JSON在JavaScript中读写结构化数据的更好的方式。JSON作为一个轻量级的数据格式,可以简化表示复杂数据结构的工作量。

语法

JSON使用JavaScript语法的子集表示对象、数组、字符串、数值、布尔值和null,但不能表示特殊值undefined。JSON字符串必须使用双引号,而不能使用单引号。JSON的书写格式为:名称/值对,键值对之间用“,”分开。名称需要使用双引号。数组则使用“[]”包含子元素。实例如下:

{ "name":["liming","papa"], "qita":"不能为undefined。可以为字符串、数值、null或布尔值", "children":[{ "name":"laoda", "qita":null },{ "name":"laoer", "qita":true }] }

解析与序列化

JSON字符串与原生JavaScript值的主要区别在于名称,JSON名称需要使用双引号,而JavaScript的属性则不需要。还有JavaScript支持undefined,而JSON不支持。ECMAScript5对解析JSON的行为进行规范,定义了全局对象JSON,JSON对象有两个方法:stringify()和parse(),分别将JavaScript对象序列化为JSON字符串和将JSON字符串解析为JavaScript值。
对于JSON.stringify()方法,除了第一个为对象外,还可以接收两个参数:过滤器(可以为数组或函数)和是否保留缩进。如果需要将对象的名字也加入JSON字符串,可以在对象中使用toJSON():functiong(){……}方法。
JSON.parse()方法也可以接收另一个参数,该参数是一个函数,将在每个键值对上调用。

Ajax

Ajax技术的核心是XMLHttpRequest对象。XHR为向服务器发送请求和解析服务器响应提供了流畅的接口。能够以异步方式从服务器取得更多消息,意味着用户点击后,可以不必刷新页面也能取得新数据。Ajax通信与数据格式无关。另外可以查看XMLHttpRequest标准

新建XMLHttpRequest对象

目前大多数浏览器都支持XMLHttpRequest(IE6之前的不支持),所以可以放心使用XMLHttpRequest。如下

使用open()启动请求

使用open启动一个请求,准备发送。最新的open()语法为:client.open(method, url [, async = true [, username = null [, password = null]]])。例子如下:

设置监听事件

一般我们将请求设为异步,可以通过onreadystatechange为xhr对象设置监听函数。接收到相应后,响应的数据会自动填充XHR对象的属性,相关的属性有:responseText、responseXML、status、statusText。

  • onreadystatechange:xhr的事件。readyState改变会触发此事件,所以通过监听此事件并检查状态确定请求所处状态
  • readyState:xhr的属性。0表示未初始化,即未调用open()方法。1表示启动,调用open()。2表示发送,调用send()。3表示接收,在接收数据。4表示完成,接收到全部响应数据。
  • responseText:xhr的属性。接收完响应后,该属性会被填充作为响应主体被返回的文本。
  • status:响应的HTTP状态。200表示成功、404表示未找到等。

设置XHR头、超时事件等

有时为了让后台可以解析我们发送的数据,我们需要设置请求头。如在发送json数据时,将Content-Type设为’application/json;charset=UTF-8’。语法为:client.setRequestHeader(header, value)。
我们可能需要设置的请求头为:Cookie、Cookie2、Host、Keep-Alive、Upgrade、Content-Type等。
此外,为了防止等待响应时间过长,我们可以设置client.timeout来设置等待时间,单位为毫秒。

处理数据并发送

新建了xhr对象,启动,并设置相关的请求头后,我们要对要发送的数据进行处理并发送。语法为:client.send([data = null])

  • 通过JSON.stringify()可以将对象转换为json数据。在解析json数据时使用JSON.parse()。
  • 如果xhr方法为GET或HEAD,忽略传入的data,设为null。
  • 如果发送的数据为对象,将对象类型作为要发送的值,如object,则发送主体为[object object]
  • 如果发送的数据为string,将Content-Type设为”text/plain;charset=UTF-8”。(注意,json也为string类型,所以发送json时,要设置请求头的内容类型)
  • 还可以发送document、FormData或ArrayBufferView类型

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
```

## 发送请求的方法
通常我们像一个url发送请求有三种方法,通过路径、query以及数据请求主体。
* 通过路径。我们制定url并不意味着这个url路径就存在。路径也可以作为请求而存在,并通过RESTful的设计,与GET、POST、PUT、DELETE四个方法结合,实现增删改查。[RESTful维基](https://www.wikiwand.com/zh/REST)
* 通过query。在使用GET方法追加请求信息时必须使用此方法。即在url后追加?key=value。
* 通过数据体。即通过数据处理,并将内容通过send(data)方法发送。GET和HEAD发送不能采用这种方式,因为会忽略data。

## GET请求和POST请求
* GET是最常见的请求类型,最常用于向服务器查询某些信息。使用频率仅次于GET的是POST请求,通常用于向服务器发送应该被保存的数据。
* GET方法不能修改服务器的内容,是绝对安全的,但要修改服务器内容,不能使用GET。而POST方法可以修改服务器的内容。
* GET将查询字符串参数值追加到URL的末尾(不能使用请求主体方式提交)。查询字符串中每个参数的名称和值都必须使用encodeURIComponent()进行编码。POST请求应该把数据作为请求的主体提交。
* POST请求的主体可以包含非常多的数据。而GET追加的字符串有限制(由于浏览器等限制)。
* GET方法将查询字符串追加到url后,相对不安全。最安全的是使用https。
* //有一个方法会缓存内容

## XMLHttpRequest 2级
#### FormData

var data = new FormData(); //方法1,先新建,再使用append方法添加
data.append(“name”,”liming”); //append()方法接收两个参数,属性和值

data = new FormData(document.form[0]); //方法2,直接传入表单,自动转换

xhr.send(data); //可以直接将formdata实例作为请求传入后台
```

超时设定

通过xhr.timeout=1000(1秒)属性设置超时。再通过xhr.ontimeout:function(){}设置超时响应事件。

进度事件

W3C定义了与客户服务器通信有关的事件(这些事件目前也被其他API借鉴)。有以下6个进度事件:

  1. loadstart:在接收到响应数据的第一个字节时触发
  2. progress:在接收响应期间持续不断地触发。可以动态地更新HTML元素的内容。如何相应头部有Content-Length字段,可以计算接收到的数据的百分比。
  3. error:在请求发生错误时触发
  4. abort: 在因为调用abort()方法时而终止连接时触发
  5. load:在接收到完整的响应数据时触发。不管状态如何,所以要检查status属性,确定数据可用性
  6. loadend:在通信完成或者触发error、abort、load事件后触发

跨域资源共享

通过XHR实现Ajax通信的一个主要限制,来源于跨域安全策略。默认情况下,XHR对象只能访问与包含它的页面位于同一个域中的资源。CORS是W3C的一个工作草案,定义了在必须访问跨域资源时,浏览器与服务器应该如何沟通,其基本思想是:利用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。除此外,还有其他跨域方法:

  1. 图像Ping,还有一种跨域请求技术是使用<\img>标签。一个网页可以从任何网页中加载图像,不用担心是否跨域。
  2. JSONP。是应用JSON的一种新方法,它由两部分组成:回调函数和数据,它非常简单易用。
  3. Comet。是一种更高级的Ajax技术。Ajax是一种从页面向服务器请求数据的技术,而Comet则是一种服务器向页面推送数据的技术。由于其实时性,非常适合处理体育比赛的分数和股票报价。
  4. SSE(服务器发送事件):围绕只读Comet交互推出的API或者模式。SSE API用于创建到服务器的单向连接,服务器可以通过连接发送任意数量的数据。
  5. Web Sockets:最令人津津乐道的新浏览器API,目标是在一个单独的持久连接上提供全双工、双向通信。它非常适合移动应用。

安全

为确保通过XHR访问的URL安全,通行的做法就是验证发送请求者是否有权限访问相应的资源。有以下几种方式可供选择:

  • 要求以SSL连接来访问可以通过XHR请求的资源
  • 要求每一次请求都要附带经过相应算法计算得到的验证码
  • 要求发送POST而不是GET请求——容易改变
  • 检查来源URL以确定是否可信——来源记录容易伪造
  • 基于cookie信息进行验证——容易伪造

表单脚本

表单的基础知识

在HTML中,表单由< form >元素来表示,而在JavaScript中,表单对应的则是HTMLFormElement类型。其有以下独有的属性和方法:

  • acceptCharset:服务器能够处理的字符集。
  • action:接受请求的URL;等价于HTML中的action特性
  • elements:表单中所有控件的集合。
  • method:要发送的HTTP请求类型,通常是“get”或“post”
  • reset();将所有表单域重置为默认值
  • submit():提交表单
  • target:用于发送请求和接受响应的窗口名称。

取得from元素的方式有多种,常见的方法有document.getElementById(“form1”)和document.forms[“form1”]。

提交表单

使用< input >和< button >都可以定义提交按钮,只要将其type特性的值设置为“submit”即可,而图像按钮则通过将< input >的type特性值设置为“image”来定义的。因此我们只要点击相应的按钮,就可以提交表单。这样,我们既有机会验证表单数据,并决定是否允许表单提交。如下:

1
2
3
4
5
6
7
8
9
var form = document.getElementById("myForm");
EventUtil.addHandler(form,"submit",function(event){
event = EventUtil.getEvent(event);

//阻止默认事件
EventUtil.preventDefault(event);
});

form.submit(); //以这种方式提交表单是不会触发“submit”事件,因此事先要先验证表单数据

此外,还可能出现用户重复提交表单。解决问题的方法有两个:

  1. 在第一次提交表单后就禁用提交按钮
  2. 利用onsubmit事件处理程序取消后序的表单提交操作。

重置表单

在用户单击重置按钮时,表单会被重置。使用type特性值为“reset”的< input >或< button >都可以创建重置按钮。此方法同样会触发“reset”事件,可以通过监听此时间,取消重置。此外,调用reset()方法也会触发reset事件,这与submit()方法不同。

表单字段

每个表单都有elements属性,该属性是表单中素有表单元素(字段)的集合。每个表单字段在elements集合中的顺序,与它们出现在标记中的顺序相同,可以按照位置和name特性来访问它们。
共有的表单字段属性、方法和事件有:

  • disabled:布尔值,表示当前字段是否被禁用
  • form:指向当前字段所属表单的指针;只读。
  • name:当前字段的名称
  • readOnly:布尔值,表示当前字段是否只读。
  • tabIndex:表示当前字段的切换序号。
  • type: 当前字段的类型,如“checkbox”等
  • value:当前字段将被提交给服务器的值。对文件字段来说,这个属性是只读的,包含着文件在计算机中的路径。
  • focus():将浏览器的焦点设置到此表单字段。
  • blur():移走焦点。仅仅是将焦点从调用这个方法的元素上面移走而已。
  • blur事件:当前字段失去焦点是触发。
  • focus事件:当前字段获得焦点时触发。
  • change事件:对于< input >和< textarea >元素,在他们失去焦点且value值改变时触发;对于< select >元素,其选项发生改变时触发。

文本框脚本

在HTML中,有两种方式来表现文本框:使用< input >元素的单行文本框和使用< textarea >元素的多行文本框。
必须将< input >元素的type属性设置为“text”才表现文本框。size指定文本框中能够显示的字符数。value可以设置文本框的初始值。而maxlength特性则用与指定文本框可以接受的最大字符数。
< textarea >始终为一个多行文本框。要指定大小可以使用rows和cols特性,分别指文本框的字符行数和列数。

选择文本

这两种文本框都支持select()方法,这个方法用于选择文本框中的所有文本。在文本框获得焦点时,选择其所有文本,这是一种常见的做法。

1
2
3
4
5
6
EventUtil.addHandler(textbox,"focus",function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);

target.select();
})

通过textbox.value.subString(textbox.selectionStart,textbox.selectionEnd)方法来获得选中的文本。

过滤输入

我们经常要求用户在文本框中输入特定的数据,或者输入特定格式的数据。所以必须使用JavaScript来完成此类过滤输入的操作。
相应向文本框中插入字符操作的是keypress事件,可以检测其对应的字符编码,再决定如何相应。比如:

1
2
3
if(!/\d/.test(String.fromCharCode(charCode))){
//如果不是数值,则……
}

自动切换焦点

在用户填写完当前字段时,自动将焦点切换到下个子弹。通常,在自动切换焦点前,必须知道用户已经输入了既定长度的数据。在keyup事件后,检测当前字符串的长度是否达到了文本框的maxlength,如果达到了,则使用focus()方法,将焦点移到下一个元素。

HTML5约束验证API

为了在将表单提交到服务器之前验证数据,HTML5新增了一些功能。有了这些功能,即便JavaScript被禁用或者由于种种原因未能加载,也可以确保基本的验证。

1
2
3
4
5
6
7
8
9
10
11
<!--required表示必填字段,适用于<input><textarea><select>等-->
<input type="text" name="username" required></input>

<!--email和url是两个得到支持最多的类型-->
<input type="email"></input>

<!--只能输入0到100的值,且必须是5的倍数-->
<input type="number" main="0" max="100" step="5" name="count"/>

<!--pattern属性,一个正则表达式,用于匹配文本框中的值-->
<input type="text" pattern="\d+" name="count" />

使用checkValidity()方法可以检测表单中某个字段是否有效。字段的值是否有效判断的一句是本节前面介绍过的那些约束。

选择框脚本

通过< select >和< option >元素创建。还有以下属性和方法

  • add(newOption,relOption):向空间中插入新的< option >元素,在相关项之前
  • multiple:布尔值,表示是否允许多选;
  • selectedIndex:基于0的选中项的索引,如果没有选中项,值为-1
  • size:选择框中可见的行数;

表单序列化

随着ajax的出现,表单序列化已经成为一种常见需求。在JavaScript中,可以利用表单的type属性,连同name和value属性一起实现对表单的序列化。在表单序列化过程中,一般不包含任何按钮字段,因为结果字符串很可能是通过其他方式提交的。

富文本编辑

富文本编辑,又称WYSIWYG(所见即所得)。可以给iframe指定一个非常简单的HTML页面作为其内容来源。这个页面在iframe中可以向其他页面一样被加载。要它可以编辑,必须要将designMode设置为“on”。另一种编辑富文本内容的方式是使用名为contenteditable的特殊属性,而且这种方法更受欢迎,因为它不需要iframe、空白页和JavaScript,值需要将元素设置为contenteditable属性即可。

事件

JavaScript与HTML之间的交互式通过事件实现的。可以通过监听器来预定事件,以便事件发生时执行相应的代码。

事件流

事件流描述的是从页面中接收事件的顺序。IE和Netscape团队提出了完全相反的事件流的概念。IE的事件流是事件冒泡流(逐级向上),Netscape Communicator的事件流是事件捕获流(逐级向下)。DOM2级事件规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。可以在最后阶段对事件做出响应。

事件处理程序

事件有click/load和mouseover等,事件处理程序的名字以“on”开头。为时间制定处理程序的方式由多种。

HTML事件处理程序

1
<input type="button" value="Click me" onclick="alert('click')" />

缺点:1.存在时差问题,可能导致时间处理程序不能执行。2.这样扩展时间处理程序的作用域链在不同浏览器中可能会导致不同结果。3.HTML与JavaScript代码紧密耦合。

DOM0级事件处理程序

1
2
3
4
5
var btn = document.getElementById("myBtn");
btn.onclick = function(){
alert("click");
}
btn.onclick = null; //删除时间处理程序

DOM2级事件处理程序

DOM2级事件定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListenter()和removeEventListener()。使用前者添加的事件,必须使用后者删除。一个事件可以引发多个事件处理程序。

1
2
3
4
5
var btn = document.getElementById("myBtn");
var handler = function(){ alert(this.id); }
btn.addEventListener("click",handler,false); //false表示冒泡阶段调用事件处理程序,true表示捕获阶段
//其他代码
btn.removeEventListener("click",handler,false); //可以。但无法移除匿名程序

IE事件处理程序

IE实现了与DOM中类似的两个方法:attachEvent()和detachEvent()。接收两个参数。事件处理程序添加到冒泡阶段。

1
2
3
4
5
var btn = document.getElementById("myBtn");
var handler = function(){ alert(this.id); }
btn.attachEvent("onclick",handler);
//其他代码
btn.detachEvent("onclick",handler; //移除

跨浏览器的事件处理程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var EventUtil = {
addHandler:functiong(element,type,handler){
if(element.addEventListener){
element.addEventListener(type,handler,false);
}else if(element.attachEvent){
element.attachEvent("on"+type,handler);
}else{
element["on"+type] = handler;
}
}

removeHandler:functiong(element,type,handler){
if(element.removeEventListener){
element.removeEventListener(type,handler,false);
}else if(element.detachEvent){
element.detachEvent("on"+type,handler);
}else{
element["on"+type] = null;
}
}
}

EventUtil.addHandler(btn,"click",handler);

事件对象

在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件有关的信息。

DOM中的事件对象

兼容DOM的浏览器会将一个event对象传入到事件处理程序中。无论指定事件处理程序时使用什么方法(DOM0或DOM2级),都会传入event对象。event常用的属性方法有:

  • currentTarget:其事件处理程序当前正在处理事件的那个元素,即事件处理程序注册的元素。等同于this。
  • target:事件的目标。最小的直接发生事件的元素。
  • type:事件的类型,即click、mouseover等。
  • prenentDefault():取消特定事件的默认行为,如点击链接导航到其href特性指定的URL
  • stopPropagation():立即停止事件在DOM层次中的传播,即取消进一步的时间捕获或冒泡。

IE中的事件对象

与访问DOM中的event对象不同,要访问IE中的event对象有几种不同的方式,取决于指定事件处理程序的方法。因为事件处理程序的作用域是根据指定它的方式来确定的,所以不能认为this始终等于事件目标,故而,最好使用event.srcElement比较保险。属性有cancelBubble(设为true可以取消事件冒泡)、returnValue(设为false可以取消事件的默认行为)、srcElement(事件的目标,等同于DOM中的target)、type(被触发的事件的类型)。

跨浏览器的事件对象

虽然DOM和IE中的event对象不同,但基于他们之间的相似性依旧可以拿出跨浏览器的方案来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var EventUtil={
addHandler://略
getEvent:function(event){
return event? event:window.event;
},
getTarget:function(event){
return event.target? event.target:event.srcElement;
},
preventDefault:function(event){
if(event.preventDefault){
event.preventDefault();
}else{
event.returnValue = false;
}
},
stopPropagation:function(event){
if(event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble = true;
}
}
}

事件类型

Web浏览器中可能发生的事件有很多类型。DOM3级事件规定了一下几类事件:

  • UI事件,当用户与页面上的元素交互时触发。
  • 焦点事件,当元素获得或失去焦点时触发。
  • 鼠标事件,当用户通过鼠标在页面上执行操作时触发。
  • 滚轮事件,当使用鼠标滚轮或类似设备时触发。
  • 文本事件:当用户在文档中输入文本时触发。
  • 键盘事件,当用户通过键盘在页面上执行操作时触发。
  • 合成事件,当为IME(输入法编辑器)输入字符时触发。
  • 变动事件,当底层DOM结构发生变化时触发。

内存和性能

在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体性能。首先,每个函数都是对象,都会占用内存。其次,必须事先指定所有事件处理程序而导致的DOM访问次数,会延迟整个页面的交互就绪时间。

事件委托

对“事件处理程序过多”的解决方案是事件委托。事件委托利用了事件冒泡,只指定了一个事件处理程序,就可以管理某一类型的所有事件。例如,可以将一个列表的点击事件交给其body元素解决,判断发生事件的元素,再执行相应的操作。

移除事件处理程序

每当将事件处理程序指定给元素时,运行中的浏览器代码与支持页面交互的JavaScript代码之间就会建立一个连接。在不需要的时候移除事件处理程序,也是解决问题的一种方案。

模拟事件

事件经常由用户操作或通过其他浏览器功能来触发,但其实也可以使用JavaScript在任意时刻来触发特定的事件,而此时的事件如同浏览器创建的事件一样。

DOM扩展及DOM2、DOM3

尽管DOM作为API已经非常完善了,但为了实现更多的功能,仍然会有一些标准或专有的扩展。W3C着手将一些已经称为事实标准的专有扩展标准化并写入规范当中。

选择符API

众多JavaScript库中最常用的一项功能,就是根据CSS选择符选择与某个模式匹配的DOM元素。jquery的核心就是通过选择符查询DOM文档取得元素的引用,从而抛开了getElementById()和getElementByTagName()。Selectors API致力于让浏览器原生支持CSS查询,这样一来,解析和树查询操作可以在浏览器内部通过编译后的代码来完成,极大地改善了性能。其核心方法有querySelector(“img.button”)和querySelectorAll(“#myDiv”),分别返回匹配的第一个元素和全部元素。
Selectors API Level2规范为Element类型新增了一个方法matchesSelector()。这个方法接收了一个参数,即CSS选择符,匹配则返回true。

元素遍历

对于元素间的空格,IE9及之前的版本不会返回文本节点,而其他浏览器都会返回文本节点。为了弥补此差异,Element Traversal API为DOM添加了5个属性:childElementCount、firstElementChild、lastElementChild、previousElementSibling、nextElementSibling。利用这些元素就不必担心空白文本节点。

HTML5

与类相关的扩充

  • getElementByClassName()方法。接收一个参数,包含一个或多个类名的字符串,类名的先后顺序不重要。返回带有指定类的所有元素的NodeList。
  • classList属性。是新集合类型DOMTokenList的实例。包含一个元素的类名列表。有方法:add() contains() remove() toggle()(如果已经存在,删除,如果没有,添加)。

焦点管理

document.activeElement属性,始终引用DOM中当前获得了焦点的元素。元素获得焦点的方式有页面加载、用户输入和在代码中调用focus()方法。

HTMLDocument的变化

  • document.readyState属性,有两个可能值:loading和complete,分别表示正在加载文档和已经加载完文档。
  • head属性。HTML5新增了document.head属性,引用文档的<\head>元素。

自定义数据属性

HTML5规定可以为元素添加非标准的属性,但要添加前缀data-,目的是为元素提供与渲染无关的信息。

innerHTML属性和outerHTML属性

  • innerHTML属性:在读模式下,innerHTML属性返回与调用元素的所有子节点对应的HTML标记。
  • outerHTML属性:在读模式下,outerHTML属性返回调用它的元素及所有子节点的HTML标记。
  • insertAdjacentHTML()方法。在特定的位置插入HTML文本。
  • 使用以上方法替换子节点可能会导致浏览器的内存占用问题。所以要避免频繁使用以上方法。

专有扩展

文档模式

页面的文档模式决定了可以使用什么功能。即,文档模式决定了可以使用哪个级别的CSS,可以在JavaScript中使用那些API,以及如何对待文档类型(doctype)。

children属性和contains()方法

  • children属性,是HTMLCollection的实例,只包含元素中同样还是元素的子节点。除此外,children属性与childNodes没有什么区别。
  • contains()方法:用于检测某个节点是不是另一个节点的后代,是则返回true

插入文本

  • innerText属性。操作元素中包含的所有文本内容,包括子文档书中的文本。会去掉元素内容
  • outerText属性。作用范围扩大到调用它的节点。在写模式喜爱,outerText会替换掉整个元素,包括子节点。

DOM2和DOM3

DOM1级主要定义的是HTML和XML文档的底层结构。DOM2和DOM3级则在这个结构的基础上引入了更多的交互能力,也支持了更高级的XML特性。DOM2和DOM3分为了许多模块,分别描述了DOM的某个非常具体的子集。

  • DOM2级核心:在1级核心基础上构建,为节点添加了更多方法和属性。
  • DOM2级视图:为文档定义了基于样式信息的不同视图。
  • DOM2级事件:说明了如何使用事件与DOM文档交换。
  • DOM2级样式:定义了如何以编程方式来访问和改变CSS样式信息。
  • DOM2级遍历和范围:引入了遍历DOM文档和选择其特定部分的新接口。
  • DOM2级HTML:在1级HTML基础上构建,添加了更多属性、方法和新接口。

CSS3主要内容

CSS指层叠样式表(cascading style sheets),样式定义如何显示HTML元素。

CSS简介

CSS样式表极大地提高了工作效率。它定义如何显示HTML元素,样式通常保存在外部的.css文件中。通过仅仅编辑一个简单的CSS文档,外部样式表就可以同时改变站点中所有页面中的布局和外观。样式表允许以多种方式规定样式信息。样式可以规定在单个的HTML元素中,在HTML页的头元素中,或在外部的CSS样式中。其优先权从高到低为:

  1. 内联样式(在HTML元素内部)
  2. 内部样式表(位于标签内部)
  3. 外部样式表(.css文件)
  4. 浏览器缺省设置

CSS语法

CSS规则有两个主要部分构成:选择器和声明。每条声明由一个属性和一个值组成。与XHTML不同,css对大小写不敏感。存在其一例外:如果涉及到与HTML文档一起工作的话,class和id名称对大小写是敏感的。例如
h1 {color:red; font-size:14px; }

CSS选择器

元素选择器

1
2
3
h1 {color:blue;font-family:sans-serif;}

<h1>这个元素的内容会引用上面的样式</h1>

选择器分组

1
2
3
h1,h2,h3,h4{color:bule;}

<h3>以上所有元素内容都会应用样式</h3>

属性选择器

1
2
3
4
a[href][title="123"]{color:#FF0000;}

<a title="123" href="http://w3school.com.cn"> 可以应用样式 </a>
<a href="http://w3school.com.cn">不可以应用样式</a>

类选择器

1
2
3
.important {color:#FF0000;}

<p class="important">还可以在.前面加元素,则既是相应元素又是相应类则满足</p>

id选择器

1
2
3
#intro{font-weight:bold;}

<p id="intro">应用样式</p>

其他

1
2
3
4
5
h1 em{color:red;}
<h1>只要有<em>这个后代元素</em>,后代元素就应用样式</h1>

h1>strong{color:red;}
<h1><em><strong>必须</strong>是子元素</em>,而不能是后代元素。不应用样式</h1>

CSS文本及字体

文本

  • text-align:center 文本行相互之间的对齐方式
  • text-indent:5em 文本缩进
  • word-spacing:-0.5em 单词间隔
  • letter-spacing:5px 字母间隔
  • text-transform:uppercase 处理文本的大小写

字体

  • font-family:Times 字体样式
  • font-size:14px 字体大小
  • font-style:italic 规定斜体

CSS盒模型

盒模型

CSS框模型从外向里分别是:外边、margin、border、padding、内边、content。

  • 内边距可分为top、right、bottom、left四个,border和margin也可以这么分。
  • 边框有三个重要部分:style、width和color。但是在CSS3中添加了很多新属性。
  • 外边距透明,即本元素的背景不能作用域外边距,另外margin-left和margin-right都设为auto可以实现水平居中。

背景

  • backgroud-color: transparent|| 格式:rgb rgba hls hlsa #ffffff red
  • backgroud-image:none||
  • backgroud-repeat:repeat||repeat-x||repeat-y||no-repeat
  • backgroud-position:改变图像在背景中的位置。
  • background-attachment:scroll||fixed

  • background-origin: padding||border||content,背景图片定位的起点

  • background-clip: border-box||padding-box||content-box,背景图像的裁剪区域
  • background-size:auto||||cover||contain,指定背景图片的尺寸
  • background-break,指定内联元素的背景图片进行平铺时的循环方式

边框

  • border-width:{1,4} | inherit
  • border-color: |transparent|inherit。在css3中,可以设置多种颜色,一种颜色对应一个像素。
  • border-style: | inherit。如none、hidden、dotted、solid等
  • border-image: 可以使用图片,比较复杂,参考标准。
  • border-radius: none|{1,4}[/{1,4}]?

盒子阴影

布局

定位

CSS定位属性允许对元素进行定位。元素定位有相对定位、绝对定位和浮动等三种。一下分别为相对定位、绝对定位和浮动定位。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# box_relative{
position:relative;
left:30px;
top:20px;
}

# box_absolute{
position:absolute;
left:30px;
top:20px;
}

# box{
float:right;
}

CSS Override

两个类

1
2
3
4
5
6
7
8
9
<style>
.pink-text {
color: pink;
}
.blue-text{
color:blue;
}
</style>

<h1 class="blue-text pink-text">Hello World!</h1>

与h1中的class的顺序无关,而与样式表中两个类的顺序有关,后者会重写前者的color属性。故上面字体的颜色是blue

ID与class

ID的优先级要高于class

inline style与id

inline style优先级高于id

绝对最高级!important

如果要保证某个属性为绝对最高级,则在属性值后加!important。如:color:blue !important;

HTML5

HTML5可以说是HTML语言+JavaScript+API+CSS的技术集合。如今的HTML标记语言已经特别为构建真正的Web应用做了调整,提供了本地存储、2D绘图、位置感知、离线支持、套接字和线程等诸多特性。

详细内容请参考W3School

HTML标记语言简介

HTML指的是超文本标记语言,它不是编程语言,而是一种标记语言。

  • HTML标记标签(tag)通常被称为HTML标签,标签通常都是成对出现的,即开始标签和闭合标签。
  • HTML文档也被称为网页,包含HTML标签和纯文本,Web浏览器的作用是读取它并以网页的形式显示它们。
  • HTML元素指的是从开始标签到结束标签的所有代码。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <!DOCTYPE HTML>
    <html>

    <head>
    meta/外部引用JavaScript/title等
    </head>>
    <body>
    h/p/table/img/div等元素
    </body>

    </html>

HTML常用标签列表

基础

标签 描述
<! DOCTYPE > 定义文档类型。
< html > 定义 HTML 文档。
< title > 定义文档的标题。
< body > 定义文档的主体。
< h1 >to< h6 > 定义HTML标题。
< p > 定义段落。
</ br > 定义简单的折行。
< hr > 定义水平线。
< !–……– > 定义注释行。
< head > 定义关于文档的信息。
< meta > 定义HTML文档的元信息
< frame > 定义框架的窗口或框架
< div > 定义文档中的节。大
< span > 定义文档中的节。小

格式

标签 描述
< bdi > html5 定义文本的文本方向。
< b > 定义粗体文字。
< i > 定义斜体文字。
< code > 定义计算机代码文本。
< mark > html5 定义有记号的文本。
< sup > < sub > 定义上标、下标文本。
< time > 定义日期/时间。
< em > 定义强调文本。

表单

标签 描述
< from > 定义供用户输入的表单
< input > 定义输入控件。
< textarea > 定义多行的文本输入控件
< button > 定义按钮。
< select > 定义下拉列表。
< label > 定义input元素的标注。
< datalist >html5 定义下拉列表。
< keygen > html5 定义生成密匙。
< output > 定义输出的一些类型。

连接及音频/视频

标签 描述
< a > 定义锚。
< link > 定义文档和外部资源的关系
< img > 定义图像。
< map > 定义图像映射。
< canvas > html5 定义图形。
< nav > html5 定义导航链接。
< audio > html5 定义声音内容。
< video > html5 定义视频。
< source > html5 定义媒介源。

列表及表格

标签 描述
< ul > 定义无序列表。
< ol > 定义有序列表。
< li > 定义列表的项目。
< dl > 定义自定义列表。
< dt > 定义自定义列表的项目
< table > 定义表格。
< caption > 定义表格标题。
< th > 定义表格中的表头单元格
< tr > 定义表格中的行。
< td > 定义表格中的单元。

HTML全局属性

属性 描述
class 规定元素的类名
id 规定元素的唯一id
lang 规定元素内容的语言

其他

  • align=”center” 居中方式,用于标题、段落等
  • bgcolor=”yellow” 背景颜色,body等块级元素
  • border=”3” 边框大小,用于表格等

DOM-文档对象模型

DOM是针对HTML和XML文档的一个API(应用程序编程接口)。DOM描绘了一个层次化的节点树,允许开发人员添加、移除和修改页面的某一部分。IE中的所有DOM对象都是COM对象的形式实现的,这意味着IE中的DOM对象与原始JavaScript对象的行为或活动特点并不一致。

节点层次

DOM可以将任何HTML或XML文档描绘成一个由多层结点构成的结构。节点分为几张不同的类型,每种类型分别表示文中的不同的信息及标记。每个结点都拥有各自的特点、数据和方法,另外也与其他结点存在某种关系。结点之间的关系构成了层次,而所有页面标记则表现为一个以特定结点为根节点的树型结构。

Node类型

DOM1级定义了一个Node接口,该接口将由DOM中的所有节点类型实现。每个结点都有一个nodeType属性,用于表明节点的类型。节点类型由在Node类型中定义的下列12个数值常量来表示,任何结点类型必然属于其中的一种:

  • Node.ELEMENT_NODE(1)
  • Node.ATTRIBUTE_NODE(2)
  • Node.TEXT_NODE(3)
  • Node.CDATA_SECTION_NODE(4)
  • Node.ENTITY_PEFERENCE_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)

可以通过节点的nodeType属性判断结点属于哪一种结点。每个结点都有一个childNodes属性,其中保存一个NodeList对象,其为一种类数组对象(并不是Array的实例),用于保存一组有序的节点。可以使用.childNodes[0]或childNodes.item(0)来访问子节点。获取节点可以使用属性:.parentNode .firstChild .lastChild .nextSibling .previousSibling。
操作节点的方法有:

  • .hasChildNodes():判断是否有子节点,有则返回true,没有则返回false
  • .appendChild(newNode):在childNodes列表末尾添加一个新节点,并返回新增的节点。如果插入已存在的结点,则改变节点的位置。
  • .insertBefore(newNode,.old):在相应的节点前添加,如果在新的结点是某个元素的子节点,则该子节点会从该元素中自动去除。
  • .replaceChild(newNode,.old):替换结点
  • removeChild(.old):移除节点。

Document类型

document对象时HTMLDocument的一个实例,表示整个HTML页面。取得特定的某个或某组元素的引用,是常用的DOM应用,Document类型为此提供了两个方法:getElementById()和getElementByTagName()。TagName指标签名称,如div、p、img等。取得元素集合后,使用.nameItem()可以获取相应name的元素。

document对象还提供了一些特殊的集合,包括document.anchors()(包含文档中所有带name属性的<\a>元素)、document.forms()(包含文档中所有的<\form>元素)、document.images()(包含文档中所有的<\img>元素)、document.links()(包含文档中所有带href的<\a>元素)。

document对象有将输入流写入到网页中的能力。有以下四个方法:write()(可以写js代码)、writeln()(在结尾处多一个/n)、open()、close()(打开关闭网页的输出流)。

Element类型

Element类型提供了对元素标签名、子节点及特性的访问,要访问元素的标签名可以用nodeName属性或tagName属性。

所有HTML元素都由HEMLElement类型表示,共有属性为:id、className、title等。操作特性的主要方法有:getAttribute(“title”)、setAttribute(“title”,”test”)、removeAttribute(“title”)。还可以使用.attributes[“id”]等来访问属性。根据HTML5规范,自定义的属性应该加上data-前缀。

可以使用document.createElement(“<\div><\/div>”)方法创建新的元素,并返回新元素,然后通过appendChild()等方法添加到文档树中。

Text类型

文本节点由Text类型表示,包含的是可以照字面解释的纯文本内容。纯文本中可以包含转义后的HTML字符,但不能包含HTML代码。

与element相同,可以通过document.createTextNode()创建新文本节点,并返回新文本节点,然后通过appendChild()等方法添加到文档树中。

使用element.normalize()和element.firstChild.splitText(5)等方法可以合并和分割文本节点。

其他类型

除以上常用类型外,还有Comment类型(注释)、CDATASection类型(显示代码)、DocumentType类型(文档类型声明)、DocumentFragment类型(仓库,可能要添加的节点)、Attr类型(特性节点)

DOM操作技术

动态脚本

使用<\script>元素可以向页面中插入JavaScript代码,一种方式是通过其src特性包含外部文件,另一种方式是通过这个元素本身包含代码。动态创建脚本也有两种:插入外部文件和直接插入JavaScript代码。此时要考虑到兼容性的问题,比如:

1
2
3
4
5
6
7
8
9
10
11
function loadScriptString(code){}
var script = document.createElement("script");
script.type = "text/javascript";
try{
script.appendChild(document.createTextNode code);
}catch(ex){
script.text = code;
}
document.body.appendChild(script);
}

loadScriptString("function asyHi(){alert('hi');}");

动态样式

能够把CSS样式包含到HTML页面中的元素由两个,其中,<\link>元素用于包含来自外部的文件,而<\style>元素用于指定嵌入的样式。

1
2
3
4
5
6
7
8
9
10
11
12
function loadStyleString(css){
var style = document.createElement("style");
style.type = "text/CSS";
try{
style.appendChild(document.createTextNode(css));
}catch(ex){
style.styleSheet.cssText = css;
}
var head = documentl.getElementByTagName("head")[0];
head.appendChild(style);
}
loadStyleString("body{backgroud-color:red}");

使用NodeList

理解NodeList及HTMLCollection和NamedNodeMap,是从整体上透彻理解DOM的关键所在。这单个集合都是“动态的”;每当文档结构发生变化,它们都会更新。从本质上说,所有NodeList对象都是在访问DOM文档时实时运行的查询,所以每次访问NodeList对象,都会进行一次查询。所以要尽量减少DOM操作。可以考虑将从NodeList中取得的值缓存起来,从而减少查询的次数。