第一章 JavaScript 简史
主要讲了JavaScript的起源和发展.
第二章 JavaScript语法
2.1 准备工作
2.2 语法
2.2.1 语句
如果你想把多条语句放在同一行上,就必须用分号来分隔开它们。
2.2.2 注释
- //自我提醒:有注释是好事
- /*自我提醒:
有注释是好事
2.2.3 变量
- javascript允许程序员直接对变量赋值而无需事先声明
- 不允许变量名中包含空格或标点符号(美元符号”$"例外)
- 一般使用驼峰格式来起变量的名字
2.2.4 数据类型
1.字符串
2.数值
3.布尔值
2.2.5 数组
2.2.6对象
2.3 操作
-
算术操作符
加号(+)是一个比较特殊的操作符,它即可以用于数值,也可以用于字符串
2.4 条件语句
-
比较操作符
-
逻辑操作符
2.5 循环语句
-
while循环
-
for循环
2.6 函数
变量的作用域
如果在某个函数中使用了var,那个变量就将被视为一个局部变量,它只存在于这个函数的上下文中;反之,如果没有使用var,那个变量就将被视为一个全局变量。
2.7 对象
-
内建对象
包括Array对象,Math对象和Date对象
-
宿主对象
由浏览器提供的预定义对象被称为宿主对象,包括Form、Image和Element等。
第三章 DOM
3.1 文档:DOM中的"D"
3.2 对象:DOM中的"O"
3.3 模型:DOM中的"M"
3.4 节点
-
元素节点
-
文本节点
-
属性节点
-
获取元素
1.getElementById
- 返回一个与那个有着给定id属性值的元素节点对应的对象
- 它是document对象特有的函数
- 可以通过typeof操作符在确定操作数是一个字符串、数组、函数、布尔值还是对象。
2.getElementsByTagName
- 返回一个对象数组,每个对象分别对应着文档里有着给定标签的一个元素。
- 运行把一个通配符"*"作为它的参数。
3.getElementsByClassName
- 返回一个与那个有着给定class属性值的元素节点对应的对象
3.5 获取和设置属性
1.getAttribute(attribute)
2.setAttribute(attribute,value)
第三章 JavaScript图片库
第五章 最佳实践
第六章 图片库的改进版
第四章将html,css与javascript运用到了JavaScript图片库上
- 为了减少对站点的请求次数(提高性能),应该把这些.js文件合并到一个文件中;
- 事件处理函数:在特定事件发生时,调用特定的JavaScriptd代码;
- nodeValue属性:用来得到和设置一个节点的值;
- 包含在<p>元素里的文本是另一个节点,它是<p>元素的第一个子节点;
- firstChild和lastChild属性,子节点的第一个和最后一个元素;
- childNodes属性:可以用来获取任何一个元素的所有子元素,是一个包含这个元素全部子元素的数组;
- onload事件处理函数:函数在页面加载时执行;
- nodeType属性:返回节点的类型;
事件处理函数的工作机制:
以onclick为例:我们给某个链接添加一个onclick事件处理函数,并让这个处理函数所触发的js代码返回布尔值true或false,这样一来,当这个链接被点击时,如果那段js代码返回的值是true,onclick事件处理函数就认为被点击了;反之,则没有被点击。
节点的类型总共有12种可取值,有3种具有实用价值:
- 元素节点的nodeType属性值是1
- 属性节点的nodeType属性值是2
- 文本节点的nodeType属性值是3
第五章介绍了最佳实践
在本章作者提出了一些好的网站应该满足的要求:
1、在使用任何一句javascript代码时,都应该想想,对这个网页是否有用;
2、平稳退化:如果正确使用了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字样;
一些新的概念:
1、“javascript"伪协议:真协议让我们在因特网上的计算机之间传输数据包,伪协议是一种非标准化的协议,让我们通过一个链接调用javascript函数;
2、浏览器嗅探技术:通过浏览器供应商提供的信息来解决向后兼容的问题。
3、document对象是window对象的一个属性,当window对象触发onload事件时,document对象已经存在,文档树就会被创建成功;
第六章对图片库进行了优化
以下是本章的一些其他要点:
1、结构化程序设计要求函数只有一个入口和出口。但只要出口集中出现在函数的开头部分就是可以接受的。
2、每个事件处理函数只能绑定一条指令。
3、nodeName属性总是返回一个大写字母的值,即时元素在HTML文档中是小写字母。
4、键盘访问:最好不要使用onkeypresss事件处理函数,onclick事件处理函数已经能满足需要,它对键盘的访问相当完美
html代码:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>javascript dom图片库</title>
<script src="javascript图片库.js"></script>
<style>
*{
margin:0;
padding:0;
}
body{
background-color:#ccc;
margin: 1em 10%;
}
h1 {
color:#333;
background-color:transparent;
}
li{
float:left;
padding: 1em;
list-style:none;
}
img,p{
display:block;
clear:both;
}
#imagegallery li{
display:inline;
}
#imagegallery li a img{
border:0;
width:100px;
height:100px;
}
</style>
</head>
<body>
<h1>Snapshots</h1>
<ul id="imagegallery">
<li>
<a href="images/1.jpg" title="a 1 display" class="showPic">
![](images/1.jpg)
</a>
</li>
<li>
<a href="http://www.baidu.com/" class="popup" title="a 2 display" onclick="popUP(this.getAttribute("href"));return false;">平稳退化</a>
</li>
<li>
<a href="images/2.jpg" class="showPic" title="a 2 display">
![](images/2.jpg)
</a>
</li>
<li>
<a href="images/3.jpg" class="showPic" title="a 3 display">
![](images/3.jpg)
</a>
</li>
<li>
<a href="images/4.jpg" class="showPic" title="a 4 display">
![](images/4.jpg)
</a>
</li>
</ul>
</body>
</html>
js代码:
function addLoadEvent(func){
//把现在的window.onload事件处理函数的值存入变量oldload
var oldonload = window.onload;
if(typeof window.onload != "function"){
//如果在这个处理函数上还没有绑定任何函数,就按平时那样把新函数添加给它。
window.onload = func;
} else{
window.onload = function(){
//如果在这个处理函数上已经绑定了函数,就把新函数添加到现有指令的末尾。
oldonload();
func();
}
}
}
addLoadEvent(preparePlaceholder);
addLoadEvent(prepareLinks);
//把占位符替换成想要的图片
function showPic(whichpic){
//进行对象检测,向后兼容,利用结构化程序设计中的“一个函数应该只有一个入口和一个出口”
if(!document.getElementById){
if(!document.getElementsByTagName){
return false;
}
}
var source = whichpic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
var gallery = document.getElementById("imagegallery");
gallery.parentNode.insertBefore(placeholder,gallery);
placeholder.setAttribute("src",source);
if(document.getElementById("description")){//不要做太多假设,当description存在才执行下面的代码,如果不存在就忽略
var text = whichpic.getAttribute("title");
var description = document.getElementById("description");
description.firstChild.nodeValue = text;
//firstChild返回元素的第一个子元素
}
}
function popUP(winURL){
window.open(winURL,"popup","width:400,height:400");
}
//实现了javascript与html的分离
function prepareLinks(){
//尽量减少访问DOM和尽量减少标记,例如下面把document.getElementsByTagName("a")存放在变量links中,使得getElementsByTagName("a")只执行了一次,后面只需要调用links;
if(!document.getElementsByTagName){
return false;
}
var links = document.getElementsByTagName("a");
if(links.length>0){
for(var i=0;i<links.length;i++){
if(links[i].getAttribute("class") == "showPic"){
links[i].onclick=function(){
//只有showPic函数执行成功才返回true
showPic(this);
console.log(showPic(this));//输出undefined
return false;
//想要阻止链接被点击后的默认行为,可以给点击事件里面的javascript代码返回一个布尔类型的值,true就代表被点击了,false就代表没有被点击
}
}
}
}
}
function preparePlaceholder(){
var gallery = document.getElementById("imagegallery");
var placeholder = document.createElement("img");
placeholder.setAttribute("id","placeholder");
placeholder.setAttribute("alt","my image gallery");
var description = document.createElement("p");
description.setAttribute("id","description");
var desctext = document.createTextNode("Choose an image");
description.appendChild(desctext);
insertAfter(placeholder,gallery);
insertAfter(description,placeholder);
}
//在现有元素后插入一个新元素
function insertAfter(newElement,targetElement){
var parent = targetElement.parentNode;
//检查targetElement是不是parent的最后一个子元素
if(parent.lastChild == targetElement){
//如果是就追加到parent元素上
parent.appendChild(newElement);
} else{
//如果不是,把新元素插入到目标元素和目标元素的下一个兄弟元素之间。其中目标元素的下一个兄弟元素即目标元素的nextSibling属性。
parent.insertBefore(newElement,targetElement.nextSibling);
}
}
第七章 动态创建标记
本章首先回顾了创建标记的方法:
一些传统的方法:
1、document.write:
违背了“行为应该与表现分离”的原则。
2、innerHTML:
并不是W3C DOM标准的组成部分,但是现在已经包含到HTML5规范里面中了。
就本属性看来,标记下只有一个字符串,其无细节可言,会永久改变原来的文档。比document.write()方法值得推荐,也是HTML专属属性,不能用于其他标记语言文档。
DOM方法:
1、只要用正确的方法,就可以获取DOM节点树上任何一个节点的细节。
2、改变显示内容,但不会改变物理内容。
3、在浏览器看来,DOM节点才是文档
4、createElement方法:
创建元素节点,只创建会出现一个文档碎片,它是游荡在javascript世界里的一个孤儿。但是它已经有nodeType和nodeName属性
appendChild方法
createTextNode方法:创建文本节点
以上三种结合使用来扩展文档树
parentElement.insertBefore(newElement,targetElement)
targetElement元素的parentNode属性值就是parentElement;
属性节点和文本节点的子元素不允许是元素节点
5、Ajax
使用Ajax可以做到只更新页面中的一小部分,其他内容不用重新加载,Ajax的主要优势是对页面的请求以异步方式发送到服务器。
XMLHttpRequest对象
浏览器脚本与服务器之间的中间人的角色。javascript可以通过这个对象自己发送请求,同时自己处理响应。
问题在于不同浏览器实现XMLHttpRequest对象的方式不太一样。
该对象最有用的是open方法:用来指定服务器上将要访问的文件,指定请求类型:GET、POST或SEND。
访问服务器发送回来的数据要通过两个属性完成,一个是responseText属性,这个属性用于保存文本字符串形式的数据,另一个属性是responseXML属性,用于保存Content-Type头部中指定为text/xml的数据。
使用Ajax需要注意同源策略:使用XMLHttpRequest对象发送的请求只能访问与其所在的HTML处于同一个域中的数据,不能像其他域发送请求,有些浏览器会限制Ajax请求使用的协议。
异步性:脚本在发送XMLHttpRequest请求之后,仍然会继续执行,不会等待响应返回。
本书推荐的三个自己构建的函数: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;
}
}