一、代码命名规范:
1. 变量使用下划线
2. 函数使用驼峰命名
二、DOM
定义:DOM是一套对文档的内容进行抽象和概念化的方法.
- D:文档 document
- O: 对象 object
- M: 模型 Model
DOM是一种适用于多种环境和多种程序设计语言的通用型API。
1. 文档是由节点构成的集合,只不过此时的节点是文档树上的树枝和树叶而已
2. 一个文档就是一颗节点树
3. 节点分类:
DOM的原子是元素节点(element node)、文本节点(text node)、属性节点(attribute node)
获取元素
通过id获取元素
//getElementById 通过id获取元素
document.getElementById("id");
//文档上每一个元素都是一个对象。利用DOM提供的方法能得到任何一个对象
通过标签名获取元素
//getElementsByTagName方法返回一个对象数组,每个对象分别对应这文档里的有着给定标签的一个元素;
document.getElementsByTagName("li")//返回文档中所有的li标签
//如果你要知道某份文档中总共由多少个元素节点,可以用通配符
document.getElmentByTagName("*").length
通过类名获取元素
//getElmentByClassName,整个方法我们能够通过class属性中的类名类访问元素
//这个方法还可以查找那些带有多个类名的元素,指定多个类名,只要在字符串参数中用空格分隔类名即可。
document.getElmentsByClassName("important sale").length
//这个getElementsByClassName方法非常有用,但只有比较新的浏览器才支持它,所以呢要自己实现这个方法
function getElementsByTagClassName(node, calssName){
if(node.getElementsByClassName){
//使用现有的方法
return node.getElementsByClassName(calssName);
}else{
var results = new Array();
var elems = node.getElementsByTagName("*");
for (var i=0;i<elems.length;i++){
if(elems[i].className.indexOf(calssName) != -1){
results[results.length] = elems[i];
}
}
}
return results;
}
获取和设置属性
1. getAttribute
* 它是一个函数,一个参数---查询属性的名字
* 不属于document对象,不能通过document调用
* object.getAttribute(attribute) 例如:obj.getAttribute("title")//获取标签title属性
2. setAttribute
* 对属性节点的值做出修改
* object.setAttribute(attribute,value)
childNodes属性
//在一棵节点树上,childNodes属性可以用来获取任何一个元素的所有子元素,它是一个包含这个元素全部子元素的数组
element.childNodes
//注意:
//由childNodes属性返回的数组包含所有类型的节点,而不仅仅是元素节点,几乎每一样东西都是一个节点,甚至连空格和换行符都会被解释为节点,而他们全都包含在childNodes属性返回的数组中。
nodeType属性
每一个节点都有nodeType属性
nodeType属性共有12种可取值,但其中仅有3种具有实用价值。
[X] 元素节点的nodeType属性值为1
[X] 属性节点的nodeType属性为为2
[X] 文本节点的nodeType属性值为3
nodeValue属性
* 如果想改变一个文本节点的值,那就使用DOM提供的nodeValue属性,它用来得到一个节点的值:
node.nodeValue
注意:
node应该是该标签的文本节点,只有文本节点才会由nodeValue。
例如: p.nodeValue 得到的是一个null值。 而你真正需要的是<p>元素所包含的文本的值。包含在<p>元素的文本是另一种节点,他是<p>元素的第一个子节点。因此你想要得到的其实是它的第一个子节点的nodeValue的属性值。
所以要这么获得: p.childNodes[0].nodeValue;
* 设置一个节点的值
p.childNodes[0].nodeValue = "666666666";
* nodeName
返回标签名称
nodeName属性总是返回一个大写字母的值
例如: if(placeholder.nodeName != "IMG") return false;
三、DHTML
DHTML是 “Dynamic HTML”(动态HTML)的简称。DHTML并不是一项新技术,而是描述HTML、CSS、JavaScript技术组合的术语。
1、利用HTML把网页标记和各种元素;
2、利用CSS设置元素样式和探秘的显示位置;
3、利用javaScript实时地操控页面和改变样式;
四、JavaScript语法
用javaScript编写的语法必须通过HTML/XHTML文档才能执行。
1. 将JavaScript代码放到文档<head>标签中的<script>标签之间:
2.典型的做法是将JavaScript代码作为一个扩展名为.js的独立文件,再文档的<head>部分放一个<script>标签,并把他的src属性指向该文件;
3.最好是把<script>标签放到HTML文档的最后,<body/>之前,这样能使浏览器更快的记载页面;
语句
多条语句放在同一行上,就必须使用分号来隔开它们:
first statement; scond statement;
注释:
1.使用双斜杠
//自我提醒:有注释是好事
注意点:使用这种注释方式,就必须再每个注释的开头加上两个斜线,例如像下面这样就会出问题
//自我提醒:
有注释是好
----------------------------分割线---------------------------------------------
2.再注释内容的开头加上一个斜线和一个星号(/*),在注释内容的末尾加上一个星号和一个斜线(/*)
/*自我提醒:
有注释是好事*/
这种注释方式在需要插入大段的注释时很有用,他可以提高整个脚本的可读性。
----------------------------分割线---------------------------------------------
3. 还可以使用HTML的注释风格,其实JavaScript解析器对"<!--"的处理与对“//”的处理是一样的:
<!--这是JavaScript中的注释
如果在HTML文档中,还需要以"-->"来注释结尾
<!--这是HTML中的注释-->
注意:
1.JavaScript不要求这样坐,它会把“-->”当作注释内容的一部分
2.HTML允许上面那样注释跨越多行,但JavaScript要求每行都必须在开通加上 “<!--” 来作为标志
3.JavaScript解释器在处理这种风格的注释时与大家所熟悉的HTML做法不同,为避免发生混淆,最好不要在JavaScript脚本中使用这种风格的注释。建议大家使用“//”来注释单行,用“/*”注释多行
变量
//对某个变量赋值之前未声名,赋值操作将自动声明该变量。(ps:虽然JavaScript没有强制要求程序员必须提前声明变量,但提前声明变量是一种良好的编程习惯)
var mood;
var age;
//不必单独声明每个变量,你也可以用一条语句一次声明多个变量
var mood, age;
//也可以一石二鸟:把声明变量和对该变量的赋值一次完成:
var mood = "happy", age = 33;
//注意点:
//变量和其他语法元素的名字都是区分大小写的(ps:MOOD 和 mood是完全不一样的)
//不允许变量包含空格或标点符号(美元符号“$”除外)
//数据类型(必须明确类型声明的语音成为强类型语言, JavaScript不要进行类型声明,因此他是一种弱类型语言 )
//1. 字符串
//字符串由零个或多个字符构成。字符串包括(但不限于)字母、数字、标点符号和空格。字符串必须包括在引号里,单引号或双引号都可以
var mood = ‘happy’;
var mood2 = "happy"; 都是可行的
//注意:如果字符串里包含双引号,就把整个整个字符串放在单引号里; 如果字符串包含单引号,就把整个字符串放在双引号里;
var mood = "don't ask";
//如果想在上面这条语句种使用单引号,就必须保证“n”和“t”之间的单引号能被当成真个字符串的一部分。这种情况下真个单引号需要被看成一个普通字符,而不是真个字符串的结束标志,这种情况我们需要对这个字符进行转义。在JavaScript里用反斜杠进行转义:
var mood = "don\'t ask";
* 类似的,如果想用双引号来包住一个本身就包含双引号的字符串,就必须用反斜杠对字符串中的双引号进行转义:
var height = "aboout 5'10\" tall";
---------------------------------------分割线----------------------------------------------------------
//2. 数组
//JavaScript中,数组可以用关键字Array声明。声明数组的同时还可以指定数组初始元素个数,也就是数组的长度:
var beatles = Array(4);
//向数组中添加元素叫做填充
array[index] = element;
//字面量初始化
var beatles = ["John","Paul","George","Ringo"];
//对象
对象时自包含的数据集合,包含在对象里的数据可以通过两种形式访问-属性(property)和方法(method):
[X] 属性时隶属于某个特定对象的变量
[X] 方法是只有某个特定对象的变量
对象就是由一些属性和方法组合在一起而构成的一个数据实体
JavaScript语言里的对象可以分为三种类型;
[X] 用户自定义对象:由程序员自行传教的对象。
[X] 内建对象:内建对象在JavaScript语言里的对象,如Array、Math和Date等;
[X] 宿主对象:由浏览器提供的对象
五、变量的作用域
- 全局变量(global varable)可以在脚本中的任何位置被引用。(ps:全局变量的作用域就是整个脚本)
局部变量(local variable)只存在于声明她的那个函数内部。(ps:局部变量的作用域仅限于某个特定的函数)
var 关键字明确的为函数变量设定作用域
如果在某个函数中使用了var,那个变量就将被视为一个局部变量,它只存在整个函数的上下文中。 反之如果没有使用var,那么变量就将被视为一个全局变量。
在定义一个函数时,我们一定要把他的内部变量全部都明确的声明为局部变量。
六、最佳实践
- 质疑一切
如果要使用JavaScript就要确认,这么做会对用户的浏览体验产生怎么样的影响?
如果用户的浏览器不支持JavaScript怎么办
- 平稳退化
- 结构样式分离
文档结构和文档样式的分离可以确保网页都能平稳退化。具备CSS支持的浏览器固然可以把网页呈现的美轮美奂,不支持或禁用了CSS功能的浏览器同样可以把网页的内容按照正常的结构显示出来。
- 渐进增强
所谓渐进增强就是用一些额外的信息去包裹原始数据。按照“渐进增强”原则创建出来的网页(如果不是“全部”的话)都符合“平稳退化”原则;
- 向后兼容
- 对象检测
//针对这一问题的最简单的解决方案是,检测浏览器对JavaScript的支持程度
//这种解决方案很容易实现:只要把某个方法打包在一个if语句里,就可以个根据这条if语句的条件表达式的求值结果是true还是false来决定应该采取怎样的行动。这种检测成为对象检测
if(method){
statement;
}
//在对象检测时,一定删掉方法名后面的圆括号,如果不删掉,测试的将是方法的结果,无论方法是否存在:
function myFunction(){
if(document.getElementById){
statements using getElementById
}
}
- 浏览器嗅探技术
- 性能考虑
尽量少访问DOM和尽量减少标记
访问DOM的方式对脚本性能会产生非常大的影响。
示例代码:
if(document.getElementsByTagName("a").length > 0){
var links = document.getElmentsByTagName("a"){
for (var i=0;i<links.length; i++){
//对每个链接做点处理
}
}
}
//首先,它取得了所有<a>元素,然后检查它们个数是不是大于0:
if(document.getElementsByTagName("a").length>0){
//然后,如果大于0,它会再次取得所有的<a>元素,循环遍历这些元素并应用某些操作;
var links = document.getElementByTagName("a");
for (var i=0; i<links.length;i++){
//虽然这段代码可以运行,但它不能保持最优的性能。不管什么时候,只要查询DOM中的某些元素,浏览器都会搜索整个DOM树,从中查找可能匹配的元素。这段代码居然使用了两次getElementByTagName方法去执行相同的操作,浪费了一次搜索。更好的办法时把第一次搜索到的结果保存在一个变量中,然后在循环里重用该结果比如
var Links = document.getElementsByTagName("a");
if(links.length > 0){
for(var i=0; i<links.length;i++){
//对每个链接做点处理
}
}
- 合并和放置脚本
包含脚本的最佳方式就是使用外部文件,因为外部文件和标记能清晰的分离开,而且浏览器也能对站点中的多个页面重用缓存过的相同脚本。
不过类似下面这种情况也不要出现:
<script scr="functionA.js"></script>
<script scr="functionB.js"></script>
<script scr="functionC.js"></script>
<script scr="functionD.js"></script>
推荐做法就是把functionA.js functionB.js functionC.js functionD合并到一个脚本文件中;
这一就可以减少加载页面时发送的请求数量。而减少请求数量通常都是在性能优化时首先要考虑的。脚本在标签中的位置对页面的初次加载时间也有很大影响。
把所有<script>标签都放在文档的末尾,</body>标记之前,就可以让页面变得更快。
- 压缩脚本
所谓压缩脚本,指的就是脚本文件中不必要的字节,如空格和注释,统统删除,从而达到“压缩”文件的目的;
六、共享onload事件
网页加载完毕时会触发一个onload事件,这个事件与window对象相关联。
window.onload = func;
这样并不是很完美,如果我有funcA funcB。如果想让他们俩都在页面加载时得到执行,如果它们逐一绑定到onload事件上,它们当中将只有最后那个才会被实际执行:
window.onload = funcA;
window.onload = funcB;
还有一个解决方法就是
window.onload = function(){
funcA();
funcB();
}
它确实能很好的工作-在需要绑定的函数不是很多的场合,这应该时最简单的解决方案了。
下面这个弹性最佳的解决方案。不管你打算在页面结束后执行多少个函数,它都应付字符。
[X] 把现有的window.onload事件处理函数的值存入变量oldonload
[X] 如果在这个梳理函数上还没有绑定任何函数,就像平时那样把新函数添加给它
[X] 如果在这个处理函数上已经绑定了一些函数,就把新函数追加到现有指令末尾;
function addLoadEvent(func){
var oldOnload = window.onload;
if (typeof window.onload != 'function' ){
window.onload = func;
}else{
window.onload = function(){
oldOnload();
func();
}
}
}
七、动态创建标记
* document.write
document 对象的write方法可以方便快捷的把字符串插入到文档中。
例如:document.write("<p>This is inserted.</p>")
缺点:它违背了“行为应该与表现分离”,避免使用document;
* innerHTML属性
现如今所有的浏览器几乎都支持属性innerHTML,这个属性并不是W3C DOM标准的组成部分。它会返回一段HTML代码
* innerHTML属性可以用来读、写某给定元素里的HTML内容
* innerHTML属性无细节可言。想要获得细节,就必须使用DOM方法和属性。标准化的DOM像手术刀一样精细,innder属性就像一把大锤那样粗放。
* 需要将一大段HTML内容插入网页时,innderHTML属性更适用。它支持读写;
* 一旦使用了innerHTML属性,他的全部内容将都被替换
* innerHTML不会返回任何对刚插入的内容的引用
* innerHTML属性要比document.write()方法更指定推荐。使用innderHTML属性,你就可以把JavaScript代码从标记中分离出来。用不着再标记的<body>部分插入<script>标签
八、DOM方法
- createElement方法
//创建一个新元素
document.createElement(nodeName);
//例如:创建一个p元素
var pTag = document.createElement("p");
- appendChild方法
//把新创建的节点插入某个文档的节点树;
parent.appendChild(child);
//例如:
var para = document.creatElement("p");
testDiv.appendChild(para);
- createTextNode方法
//创建文本节点
document.creatTextNode(text);
//例如:创建一个"Hello world"的文本节点
var text = document.createTextNode("Hello world");
para.appendChild(text);
//完整代码
window.onload = function(){
var para = document.createElement("p");
var txt = document.createTextNode("Hello world");
para.appendChild(txt);
var testDiv = document.getElementById("testDiv");
textDiv.appendChild(para);
}
insertBefore()方法
在已有元素前插入一个新元素
调用此方法,你必须高速它三件事
(1)新元素:你想插入的元素(newElment)
(2)目标元素:你想把这个新元素插入到哪个元素(targetElement)之前
(3)父元素:目标元素的父元素(parentElement)
下面是这个方法的调用语法
parentElement.insetBefore(newElement,targetElement);
在已有元素后面加入一个元素
这个方法js并没有给我们实现我们就要自己实现了
function insertAfter(newElement,targetElement){
var parent = targetElement.parentNode;
if (parent.lastChild == targetElement){
parent.appendChild(newElement);
}else{
parent.insertBefore(newElement, targetElement.nextSibling);
}
}