七、匿名函数
- 最有效的类型继承:寄生组合式
- 函数签名:函数名称+参数列表
- 匿名函数:即拉姆达函数。任何函数表达式都可认为是匿名函数(没有引用它们的确定的方式);
- 递归函数:递归函数应该始终使用arguments.callee来递归地调用自身,不要使用函数名(函数名可能会发生变化)。
function factorial(num){ //经典的递归阶乘函数
if(num<=1){
return 1;
}else{
return num*factorial(num-1);
//return num*arguments.callee(num-1);
}
}
//若之后factoral=null;再执行递归函数会报错
var temp=factorial;
factoral=null;
temp(4); //出错 - 闭包:有权访问另一个函数作用域中的变量的函数。当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了闭包。
- 作用域链:指向变量对象的指针列表,它仅引用变量对象
- 函数执行完毕后,局部活动对象会销毁,内存中仅保存全局作用域。但是,若闭包中的内部匿名函数的作用域链仍然引用外部函数的活动对象,则外部函数执行完毕该活动对象不会销毁,直到匿名函数被销毁(可解除对匿名函数的引用,来释放内存)。
- 闭包的作用域链:内部匿名函数活动对象 ->外部函数活动对象 -> 全局作用域(全局执行环境的变量对象)
- 闭包保存的是整个变量对象,若外部函数变量发生变化,则内部函数取得的是最后变化的内容。
- this对象:在运行时基于函数的执行环境绑定。在全局函数中,this==window,而当函数被作为某个对象A的方法调用时,this==A。
匿名函数的执行环境具有全局性,因此其this对象通常指向window(除非通过call()或apply()改变)。 - 闭包的内存泄露:如闭包的作用域链保存着一个HTML元素,因为DOM的垃圾回收策略(引用计数),只要闭包的匿名函数存在,则该HTML元素永远不会被回收。
- 块级作用域:JS没有块级作用域,可以使用匿名函数模拟,例如:
(function(){
//块级作用域
})()
这种技术通常在全局作用域中被用在函数外部,来限制向全局作用域中添加过多的变量和函数。 - 私有变量:JS没有私有成员的感念,所有对象属性都是公有的。但任何函数中定义的变量都可当成私有变量。私有变量包括函数的参数、局部变量、内部函数。
八、浏览器对象模型BOM
概述:BOM提供与浏览器的互操作性,没有标准的BOM实现或接口
- window:BOM的核心对象,表示浏览器的一个实例。即是JS访问浏览器窗口的接口也是ECMAScript规定的Global对象。
- 框架:每个框架都用于自己的window对象。
- top对象始终指向最高层的框架,可用top.frames[0]或top.frams["topFrame"]获取内部框架。
parent对象始终指向直接上层框架。
<frameset rows="160,*">
<frame src="frame.htm" name="topFrame"/>
<frameset cols="50%,50%">
<frame src="left.htm" name=" leftFrame"/>
<frame src="right.htm" name="rightFrame"/>
</frameset>
</frameset>
screenLeft/ screenTop :IE、Safari、Opera、Chrome
screenX/ screenY :FireFox 、Safari、Chrome 窗口大小:innerWidth、innerHeight、outerWidth、outerHeight 导航和打开窗口
var myWin=window.open("http://www.baidu.com","topFrame");
myWin.resizeTo(500,100);
myWin.moveTo(100,100);
myWin.close(); 间歇和超时调用
//超时调用setTimeout,返回一个超时调用的数值ID
var timeoutId=setTimeout(function(){
//this==window
},1000);//1000毫秒
clearTimeout(timeoutId);//完全取消超时调用
//间歇调用setInterval,clearInterval和超时调用代码相似,间歇调用会间歇地不停执行。
//因为后一个间歇调用可能在前一个间歇调用还没执行完时调用,所以一般不用它,而使用超时调用来模拟间歇调用。 九、客户端检测
概述:
- 能力(特性)检测:不关心是什么浏览器而关心支持什么属性。
概述:文档对象模型是针对HTML和XML文档的一个API。
- 节点类型:ELEMENT_NODE(1),TEXT_NODE(3),DOCUMENT_NODE(9)
- 节点关系:firstChild,lastChild,previousSibling,nextSibling,parentNode。
childNodes(childNodes[0]是引用childNodes.item(0)) - 节点操作:appendChild(),insertBefore(),replaceChild(),removeChild()
- 公有方法:所有节点均有的方法,cloneNode(true深复制/false),normalize()(删除空文本或者合并相邻文本节点)
- document:该对象是HTMLDocument(继承自Document)的一个实例。
- document.documentElement为html的引用。
- 其他属性:title设置文档标题;url完整的URL;domain域名(域名相同的框架页面可以互相访问JS对象);referrer来源页面的URL。
- 查找元素:getElementById();getElementsByTagName() (若返回images,images["myImage"]是引用images.namedItem("myImage")) ;getElementsByName()。
- 特殊属性集合:anchors所有带name特性的<a>元素;forms;images;links文档中所有带href的<a>元素。
十二、事件
- 事件流阶段:捕获->目标->冒泡。(DOM2级事件)
- 事件处理程序:响应某个事件的函数,或叫事件监听器。
- DOM0级:即传统方式,简单,跨浏览器。
btn.οnclick=function(e){//e.type=="click"//IE无e这个参数,window.event.type=="click"} - DOM2级:使用注册和移除监听事件的方法。
btn.addEventListener("click",function(e){
//this==btn
},false);//第三个参数true捕获阶段调用、false为冒泡阶段调用。
btn.removeEventListener("click",handler,false);//handler必须是明确的函数引用,若为匿名函数则无效。
注:多播事件按添加顺序执行。
IE的事件处理程序(只支持冒泡阶段):
btn.attachEvent("onclick", function(e){
//this==window
} );
btn.detachEvent("onclick",handler);
注:多播事件按添加顺序反向执行。
- DOM:
body.οnclick=function(e){
e.currentTarget;//处理事件的元素,this== e.currentTarget==body
e.target;//目标对象,若是按钮触发则是指该按钮
e.eventPhase;//事件阶段码(Integer),1.捕获,2.目标,3.冒泡
e.stopPropagation();//立即停止事件的传播,即取消进一步的捕获或冒泡
e.preventDefault();//取消事件的默认行为,仅当e.cancelable=true是有效。
//一旦事件处理程序完成,e对象就会销毁
} - IE:
btn.οnclick=function(){
var e=window.event;//DOM0级方法添加事件函数时,event对象作为window的对象存在。
e. srcElement === this;//true
}
btn.attachEvent("onclick",function(e){
e.srcElement === this;//false
e.cancelBubble = true;//取消事件冒泡
e.returnValue = false;//阻止事件的默认行为
});
- UI事件:用户与页面元素交互时触发。
- 鼠标事件:鼠标
- 键盘事件:键盘
- HTML事件:浏览器窗口变化或发生特定的客户端/服务器交互时触发。
- 变动事件:底层DOM结构发生变化时触发。
- click:主鼠标单击或者回车键
- dbclick
- mousedown
- mouseout
- mouseover
- mouseup
- mousemove
- 客户区坐标:e.clientX、e.clientY。相对于浏览器可视区域。
- 屏幕坐标:e.screenX、e.screenY。相对于电脑屏幕的位置。
- load:window的load会在页面中的一切都加载完毕才触发。图片加载完毕在<img>触发。
- unload
- abort
- error
- select
- submit
- reset
- resize
- scroll
- focus
- blur
- 节点移除
- 节点插入
- 特性变化
- 文本变化
- 上下文菜单事件:contextmenu (全支持)
- 卸载前事件:beforeload (全支持)
- 鼠标滚轮事件:mousewheel(全支持)
- DOMMouseScroll事件:Firefox类似鼠标滚轮的事件
- DOMMContentLoaded事件:在形成完整的DOM数之后触发。(仅FireFox,Chrome,Safari3.1以上和Opera9以上支持)
//对于不支持该事件的浏览器,建议如下面为页面中设置第一个超时调用(0毫秒)。即便如此仍无法保证一定早于load事件
//“在当前JS处理完成后立即运行这个函数”,页面下载和构建只有一个JS处理过程,该过程结束会立即调用此超时调用
setTimeout(function(){
//在此添加事件处理程序
},0); - 就绪状态变化事件:readystatechange,IE和Opera支持,但效果不一
- 页面显示、隐藏时间:pageshow/pagehide,针对与FireFox和Opera的往返缓存。
- 事件委托:在DOM树中尽量最高层添加事件处理程序,内部元素的事件冒泡到这一个函数中处理。以解决事件过多产生的性能问题。mouseover和mouseout需计算元素的位置,故不适合事件委托。
- 移除事件处理函数:DOM中移除的元素中带有事件处理函数,若不移除函数则极可能无法垃圾回收。
btn.οnclick=null;//移除事件处理程序 - 浏览器卸载页面前移除所有的事件处理函数
- DOM:document.createEvent(eventType)
- IE:document.createEventObject()返回通用的event对象
概述: 表单即<form>元素,属于HTMLFormElement类型。
- 独有属性和方法
- acceptCharset:服务器能够处理的字符集,等价于HTML的accept-charset。
- action:接收请求的URL,等价于HTML的action特性
- elements:表单中所有控件的集合(HTMLCollection)。
- 取得表单域:form.elements[0]==form[0];form.elements["name"]=form["name"]。若有重复name则返回NodeList。
- enctype:请求的编码类型,等价于HTML的enctype。
- length:表单中的控件数量。
- method:要发送的HTTP请求类型,get、post。等价于HTML的method。
- name:表单的名称,等价于HTML的name。
- reset():将所有的表单域重置为默认值。form.reset()会触发reset事件。
- submit():提交表单。<input type="image" >与<button type="submit">按回车即会提交焦点下的表单。直接使用form.submit()不会触发submit事件。避免重复提交需监听submit事件(不要监听click)禁止按钮。
- target:用于发送请求和接收响应的窗口名称,等价于HTML的target。
- 公有表单域属性
- disabled:禁止当前域
- form:表单指针,只读
- name:域名称
- readOnly:是否只读
- tabIndex:tab序号
- type:域类型,如“checkbox”,“radio”
- value:域提交给服务器的值。文件域时为只读,包含文件在计算机中的路径。
- 公有表单域方法
- focus()
- blur()
- 公有表单域事件
- blur
- change:<input><textarea>失去焦点且value改变时触发;<select>选项改变时触发。
- focus
- 文本域
- 单行<input type="text" size="25" maxlength="50" value="初始值">显示25字符,输入最长50字符
- 多行<textarea rows="25" cols="5">初始值</textarea>没有指定最大字符的属性
- 读取和设置值:textField.value = "新的值"。最好不用DOM方法修改value,因其不一定能反映在DOM中。
- 选择文本:select(),选中域中所有文本。会触发select事件(Safari,Chrome除外)
- 读取选择的文本
- function getSelectedText(textbox){
if(document.selection){
return document.selection.creatRange().text;//IE
}else{
return textbox.value.substring(textbox.selectionStart,textbox.selectionEnd);
}
}
- textbox.value = "Hello world!";
//选择所有文本
textbox.setSelectionRange(0,textbox.value.length);//"Hello world!"
//选择前3个字符
textbox.setSelectionRange(0,3);//"Hel"
//选择第5到第7,不包括索引7,7-4=3个字符,类似于substring()的参数
textbox.setSelectionRange(4,7);//"o w"
//获取焦点,用户才能看见选择的文本
textbox.focus(); - //IE代码
var range = textbox.createTextRange();//创建范围对象
range.collapse(true);//范围折叠到开始位置
range.moveStart("character",4);//指定起点
range.moveEnd("character",7-4);//指定终点
range.select();//选择文本
//获取焦点,用户才能看见选择的文本
textbox.focus();
- 屏蔽字符
- 屏蔽所有按键:keypress事件里禁止默认行为
- 屏蔽部分按键:
//屏蔽非数字
if(!/\d/.test(String.fromCharCode(charCode))&&charCode>9&&!e.ctrlKey){//charCode为字符编码
//charCode>9用于兼容其他常用按键如上下键,退格和删除键,例如FireFox为0
//!e.ctrlKey不屏蔽ctrl与数字的组合键
//preventDefault(e),禁止默认行为
}
- 操作剪贴板
- beforecopy/copy
- beforecut/cut
- beforepaste/paste
- 自动切换焦点
- 由<select><option>元素创建
- <select>元素,HTMLSelectElement类型的属性和方法
-
- type:"select-one","select-multiple"
- add(newOption,relOption):指定项之前插入新的项
- multiple:是否允许多选
- options:控件中所以<option>元素的HTMLCollection。
- remove(index):移除指定位置的选项。
- selectedIndex :保存选择项中的第一项的索引,无选中则为-1。可设置选中指定索引的选项(会取消已有的选项)。
- size:选择框中可见的行数。
- value:无选择项则为空串;有一选择项则为该项的value(若无value属性则为该项的显示文本);多选项则以第一项为准。
- <option>元素,HTMLOptionElement类型的属性和方法
- index: 选项 在options集合中的索引。
- label: 选项 的标签。
- selected:是否被选中,可设置为true选中该项。
- text: 选项 的文本。
- value:选项的值。
- selectbox.selectedIndex=0;//选择第一项,会反选已选的选择项。
- selectbox.options[0].selected=true;//多选类型时,不会反选已选的选项;单选类型时, 会反选已选的选项。
- for(var i=0, len=selectbox.options.length; i<len; i++){
// option.selected 循环遍历获取所有选择项
}
- DOM方式
var newOption = document.createElement("option");
newOption.appendChild(document.createTextNode("Option text));
newOption.setAttribute("value", "Option value");
selectbox.appendChild(newOption);//insertBefore() - 构造函数
//最佳方案
var newOption = new Option("Option text","Option value");
selectbox.add(newOption,undefined);//末尾追加
- DOM方式
selectbox.removeChild(selectbox.options[0]);//移除第一项 - 自身函数
selectbox.remove(0); - 遗留机制
selectbox.options[0]=null;
- 将一个选择框的选项移动到另一个选择框中
selectbox2.appendChild(selectbox1.options[0]);//appendChild传入已有的元素会先从父节点selectbox1中移除它 - 在选择框中重新排序
var optionToMove = selectbox.options[1];
selectbox.insertBefore(optionToMove, selectbox.options[optionToMove.index-1]);//选项前移
概述: ECMAScript第3版引入try-catch和throw语句以及一些错误类型,来处理错误。
- 浏览器错误报告
- 错误类型
- Error:基础错误
- EvalError:eval()异常
- RangeError:范围异常
- ReferenceError:未找到对象异常
- SyntaxError:eval("a++b"),eval执行错误的语法会抛出该错误
- TypeError:变量的类型不符合要求
- URIError:encodeURI()/decodeURI(),URI格式不正确。
- 错误处理
try {
//可能异常的代码
throw 12345;
throw "Hi";
throw true;
throw { name: "JS"};
throw new Error("It's Error");
} catch (error) {
//error.message
} finally {
//一定会执行的代码,即使try中包含return也会被忽略
} - 错误处理策略
- 重点关注的错误类型
-
- 类型转换错误
- 数据类型错误
- 通信错误
十五、JavaScript与XML
十六、E4X
十七、AJAX与JSON
十八、高级技巧
十九、客户端存储
二十、最佳实践