chapter1 javascript基础
1.1 变量类型和声明
javascript 里常用基本类型有:boolean,string 和 number,常用的类分别是:Boolean,String和Number,Array,Object. 声明变量用var,不能用关键字和保留字作变量名(关键字和保留字见附录A1).命名的最佳实践是使用匈牙利命名法.
基本类型的变量声明如下:
var
iValue
=
”
5
” ;
//
声明并定义数值变量.
var sValue = ”test”; // 声明并定义字符变量.
var oText; // 声明变量.
var bValue = true ; // 声明并定义布尔变量.
var sValue = ”test”; // 声明并定义字符变量.
var oText; // 声明变量.
var bValue = true ; // 声明并定义布尔变量.
可以用typeof 函数检查变量的类型:
alert(
"
iValue's type is:
"
+
typeof
(iValue));
alert( " sValue's type is: " + typeof (sValue));
alert( " oText's type is: " + typeof (oText));
alert( " bValue's type is: " + typeof (bValue));
alert( " sValue's type is: " + typeof (sValue));
alert( " oText's type is: " + typeof (oText));
alert( " bValue's type is: " + typeof (bValue));
可以看到第三个语句中typeof(oText)的计算结果是undefined. 如果对象没有声明,或仅声明而没有初始化,那么它的值就是undefined.
用类声明变量的例子如下:
var
oNumber
=
new
Number(
5
);
var oNumber = new Number( 5 );
var oString = new String( " test " );
var oObject = new Object();
var oBoolean = new Boolean( true );
alert( " oNumber's value is: " + oNumber.valueOf());
alert( " oString's value is: " + oString.valueOf());
alert( " oObject's value is: " + oObject.valueOf());
alert( " oBoolean's value is: " + oBoolean.valueOf());
alert( " oNumber's type is: " + typeof (oNumber));
alert( " oString's type is: " + typeof (oString));
alert( " oObject's type is: " + typeof (oObject));
alert( " oBoolean's type is: " + typeof (oBoolean));
var oNumber = new Number( 5 );
var oString = new String( " test " );
var oObject = new Object();
var oBoolean = new Boolean( true );
alert( " oNumber's value is: " + oNumber.valueOf());
alert( " oString's value is: " + oString.valueOf());
alert( " oObject's value is: " + oObject.valueOf());
alert( " oBoolean's value is: " + oBoolean.valueOf());
alert( " oNumber's type is: " + typeof (oNumber));
alert( " oString's type is: " + typeof (oString));
alert( " oObject's type is: " + typeof (oObject));
alert( " oBoolean's type is: " + typeof (oBoolean));
可以看到上例中,用类的声明方式来定义变量,调用类的valueOf函数后得到和例子1.1相同的变量值(除了声明为Object的变量).还可以发现上述例子中所有typeof函数运算的结果都是object.
在这种情况下你并不能检查出变量的具体类型,所以你必须使用instanceof 函数去判断变量类型:
alert(
"
oNumber's class is Number?:
"
+
(oNumber
instanceof
Number));
虽然用类声明变量能得到同样正确的结果,但在声明变量的时候,能够使用基本类型就尽量使用基本类型.
1.2 函数声明和调用
函数的声明和调用如下:
function
doAdd(iNum1,iNum2){
// 带返回值的函数.
return iNum1 + iNum2;
}
function sayHi(sName){
// 无返回值的函数.
alert( " Hello, " + sName + " ! " );
}
alert(doAdd( 1 , 2 ));
sayHi( " Diego " );
// 带返回值的函数.
return iNum1 + iNum2;
}
function sayHi(sName){
// 无返回值的函数.
alert( " Hello, " + sName + " ! " );
}
alert(doAdd( 1 , 2 ));
sayHi( " Diego " );
1.3 Array和Object
Array类似java的List,其长度是自动增长的,使用很方便.基本用法如下所示:
var
aSample
=
new
Array();
//
声明方式一
aSample = []; // 声明方式二
// 对数组元素赋值
aSample[ 0 ] = 1 ;
aSample[ 1 ] = " test " ;
// 输出值
alert(aSample[ 0 ]);
alert(aSample[ 1 ]);
aSample = []; // 声明方式二
// 对数组元素赋值
aSample[ 0 ] = 1 ;
aSample[ 1 ] = " test " ;
// 输出值
alert(aSample[ 0 ]);
alert(aSample[ 1 ]);
使用Object,你能够定义自己的类(以后会进一步讨论).在目前你只需要知道,它相当于java里的Map类型和VB里的Dictionary类型而供你使用:
var
oSample
=
new
Object();
//
声明方式一
oSample = {}; // 声明方式二
// 将其作为Map对象使用.
oSample[ " name " ] = " Diego " ;
oSample[ " gendar " ] = " male " ;
// 更方便的声明属性的方式.
oSample.city = " Shenzhen " ;
// 输出值
alert(oSample.name);
alert(oSample.gendar);
alert(oSample.city);
oSample = {}; // 声明方式二
// 将其作为Map对象使用.
oSample[ " name " ] = " Diego " ;
oSample[ " gendar " ] = " male " ;
// 更方便的声明属性的方式.
oSample.city = " Shenzhen " ;
// 输出值
alert(oSample.name);
alert(oSample.gendar);
alert(oSample.city);
1.4 语句
流程控制语句,if-else 和 switch-case :
function
getMax(iNum1,iNum2){
// 顺带展示?的用法.
return iNum1 > iNum2 ? iNum1:iNum2;
}
function getColor(sColor){
var sValue = "" ;
switch (sColor){
case " FF0000 " :
sValue = " Red " ;
break ;
case " FFFFFF " :
sValue = " Black " ;
break ;
default :
sValue = " unknown " ;
}
return sValue;
}
// 顺带展示?的用法.
return iNum1 > iNum2 ? iNum1:iNum2;
}
function getColor(sColor){
var sValue = "" ;
switch (sColor){
case " FF0000 " :
sValue = " Red " ;
break ;
case " FFFFFF " :
sValue = " Black " ;
break ;
default :
sValue = " unknown " ;
}
return sValue;
}
常用的迭代语句有: for.. while , do-while ,有一个方便应用于Object类的语句 for ..in.. ,还有用于退出流程语句的continue 和break:
//
for 语句用法.
var aSample = new Array(); // 声明方式一
aSample = []; // 声明方式二
// 对数组元素赋值
aSample[ 0 ] = 1 ;
aSample[ 1 ] = " test " ;
// 输出值
for ( var i = 0 ;i < aSample.length;i ++ ){
alert(aSample[i]);
}
// for in 语句用法.
var oSample = new Object(); // 声明方式一
oSample = {}; // 声明方式二
// 将其作为Map对象使用.
oSample[ " name " ] = " Diego " ;
oSample[ " gendar " ] = " male " ;
// 更方便的声明属性的方式.
oSample.city = " Shenzhen " ;
// 遍历对象属性
for (prop in oSample){
alert( " prop's name is: " + prop);
}
// while 语句用法
var i = 0 ;
while (i < 5 ){
alert(aSample[i]);
i ++ ;
}
// do-while,continue 和 break:
var k = 0 ;
do {
alert(aSample[k]);
k ++ ;
if (k < 3 ){
alert( " Loop continue: " );
continue ;
} else {
alert( " Loop end: " );
break ;
}
} while ( true )
var aSample = new Array(); // 声明方式一
aSample = []; // 声明方式二
// 对数组元素赋值
aSample[ 0 ] = 1 ;
aSample[ 1 ] = " test " ;
// 输出值
for ( var i = 0 ;i < aSample.length;i ++ ){
alert(aSample[i]);
}
// for in 语句用法.
var oSample = new Object(); // 声明方式一
oSample = {}; // 声明方式二
// 将其作为Map对象使用.
oSample[ " name " ] = " Diego " ;
oSample[ " gendar " ] = " male " ;
// 更方便的声明属性的方式.
oSample.city = " Shenzhen " ;
// 遍历对象属性
for (prop in oSample){
alert( " prop's name is: " + prop);
}
// while 语句用法
var i = 0 ;
while (i < 5 ){
alert(aSample[i]);
i ++ ;
}
// do-while,continue 和 break:
var k = 0 ;
do {
alert(aSample[k]);
k ++ ;
if (k < 3 ){
alert( " Loop continue: " );
continue ;
} else {
alert( " Loop end: " );
break ;
}
} while ( true )
Chapter2 浏览器的事件模型
2.1 事件机制
事件(event)表示浏览器或用户的行为.例如浏览器装载页面后的onload事件,用户单击鼠标的onclick事件或敲击键盘的onkeydown 事件.事件处理程序(event handler,也称为event listener)表示与该事件相联系的处理函数.事件发生之后可以被多个事件处理程序所处理,这称为事件流(event flow).不同的浏览器实现事件流的模型不一定相同,IE采用冒泡型机制,而DOM标准既采用捕获型也采用冒泡型机制.
所谓冒泡型机制,指事件在特定目标发生之后,依次沿着父元素外传.如下程序所示:
<!
DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
>
< html >
< head >
< title > Sample2.1.1 </ title >
< style style ="text/css" >
.parent { width : 350px ; height : 300px ; background-color : red ; }
.child { width : 150px ; height : 100px ; background-color : blue ; }
</ style >
< script >
//
function parentAlert(){
alert('This is parent div ! ');
}
function childAlert(){
alert('This is child div ! ');
}
function bodyAlert(){
alert('This is body div ! ');
}
</ script >
</ head >
< body onclick ="bodyAlert();" >
< div id ="parentDiv" class ="parent" onclick ="parentAlert();" >
< div id ="childDiv" class ="child" onclick ="childAlert();" >
</ div >
</ div >
</ body >
</ html >
< html >
< head >
< title > Sample2.1.1 </ title >
< style style ="text/css" >
.parent { width : 350px ; height : 300px ; background-color : red ; }
.child { width : 150px ; height : 100px ; background-color : blue ; }
</ style >
< script >
//
function parentAlert(){
alert('This is parent div ! ');
}
function childAlert(){
alert('This is child div ! ');
}
function bodyAlert(){
alert('This is body div ! ');
}
</ script >
</ head >
< body onclick ="bodyAlert();" >
< div id ="parentDiv" class ="parent" onclick ="parentAlert();" >
< div id ="childDiv" class ="child" onclick ="childAlert();" >
</ div >
</ div >
</ body >
</ html >
你可以看到,事件从最内层的div发生之后,沿着层级依次上升,父div和顶层元素body都能捕获该事件并进行处理.
所谓捕获型机制和冒泡型正好相反,事件从最外层的元素发生,依次传到最内层元素,然后再传回最外层元素.由于各浏览器默认支持冒泡型机制,所以在这里不过多讨论捕获型事件流.
2.2 事件处理程序(event handler)
如下,可以在html元素指定事件处理程序,也可以用javascript代码指定:
<
html
>
< head >
< style type ="text/css" >
.divCls { width : 150px ; height : 100px ; background-color : #0000CC }
</ style >
</ head >
< script >
function clickListener1(){
alert( " method1 " );
}
function clickListener2(){
alert( " method2 " );
}
function attachAnotherFunc1(){
oEle = document.getElementById( " oDiv " );
oEle.onclick = clickListener2;
}
function attachAnotherFunc2(){
oEle = document.getElementById( " oDiv " );
oEle.onclick = function (){
alert( " method3 " );
}
}
</ script >
< body >
< div id ="oDiv" class ="divCls" onclick ="clickListener1();" />< br >< br >< br >< br >< br >< br >< br >< br >< br >< br >
< input type ="button" value ="Change listener to 2" onClick ="attachAnotherFunc1();" />
< input type ="button" value ="Change listener to 3" onClick ="attachAnotherFunc2();" />
</ body >
</ html >
< head >
< style type ="text/css" >
.divCls { width : 150px ; height : 100px ; background-color : #0000CC }
</ style >
</ head >
< script >
function clickListener1(){
alert( " method1 " );
}
function clickListener2(){
alert( " method2 " );
}
function attachAnotherFunc1(){
oEle = document.getElementById( " oDiv " );
oEle.onclick = clickListener2;
}
function attachAnotherFunc2(){
oEle = document.getElementById( " oDiv " );
oEle.onclick = function (){
alert( " method3 " );
}
}
</ script >
< body >
< div id ="oDiv" class ="divCls" onclick ="clickListener1();" />< br >< br >< br >< br >< br >< br >< br >< br >< br >< br >
< input type ="button" value ="Change listener to 2" onClick ="attachAnotherFunc1();" />
< input type ="button" value ="Change listener to 3" onClick ="attachAnotherFunc2();" />
</ body >
</ html >
还可以添加多个事件处理程序,但在IE和DOM中的处理不同:
IE:
[Object].attachEvent(“name_of_event_handler”,fnEventHandler);
[Object].detachEvent(“name_of_event_handler”,fnEventHandler);
DOM:
[Object].detachEvent(“name_of_event_handler”,fnEventHandler);
[Object].addEventListener(“name_of_event_handler”,fnEventHandler,bIsInCaptureTime); //bIsInCaptureTime表示捕获阶段.一般用false
[Object].removeEventListener(“name_of_event_handler”,fnEventHandler,bIsInCaptureTime);
[Object].removeEventListener(“name_of_event_handler”,fnEventHandler,bIsInCaptureTime);
例如:
oDiv.addEventListener(“click”,fnClick,false);
oDiv.removeEventListener(“click”,fnClick,false);
oDiv.removeEventListener(“click”,fnClick,false);
如此则可以将多个事件处理程序附加给对象.
2.3 事件对象
在事件发生的时候,事件对象(Event)会被创建.在IE,可以用如下方法取得事件对象:
var
oEvent
=
window.event;
而在DOM中,你可以在调用函数时传入event关键字,或者在函数内取第一个参数:
var
oEvent
=
arguments[
0
];
取得事件对象的目的是完成如下任务:
1) 检测事件发生时键盘鼠标的按键
2) 事件发生时对象的坐标(可以创建绚丽的动画效果)
事件对象有许多属性方法帮助你达到上述目标.可是IE和DOM的实现并不完全相同.
IE和DOM相似的属性有:
var
sType
=
oEvent.type;
//
事件类型
var iKeyCode = oEvent.keyCode; // keydown或keyup事件中获得按键数值代码.
var bShift = oEvent.shiftKey;
var bAlt = oEvent.altKey;
var bCtrl = oEvent.ctrlKey; // 是否按下shift,alt或ctrl键.
var iClientX = oEvent.clientX;
var iClientY = oEvent.clientY; // 鼠标指针在客户端区域的位置.
var iScreenX = oEvent.screenX;
var iScreenY = oEvent.screenY; // 鼠标指针在屏幕区域的位置.
var iKeyCode = oEvent.keyCode; // keydown或keyup事件中获得按键数值代码.
var bShift = oEvent.shiftKey;
var bAlt = oEvent.altKey;
var bCtrl = oEvent.ctrlKey; // 是否按下shift,alt或ctrl键.
var iClientX = oEvent.clientX;
var iClientY = oEvent.clientY; // 鼠标指针在客户端区域的位置.
var iScreenX = oEvent.screenX;
var iScreenY = oEvent.screenY; // 鼠标指针在屏幕区域的位置.
IE和DOM不相似的属性方法有:
获取发生事件的对象:
var
oTarget
=
oEvent.srcElement;
//
IE
var oTarget = oEvent.target; // DOM
var oTarget = oEvent.target; // DOM
阻止事件的默认行为(例如禁止鼠标右键)
oEvent.returnValue
=
false
;
//
IE
oEvent.preventDefault(); // DOM
oEvent.preventDefault(); // DOM
阻止事件冒泡
oEvent.cancelBubble
=
true
;
//
IE
oEvent.stopPropagation(); // DOM
oEvent.stopPropagation(); // DOM
Chater 3 Document和浏览器
3.1 访问文档节点的常用函数
最常用访问文档对象的函数有:document.getElementById 和 document.getElementsByName , 如下例子:
function
testSelect(){
var aOpts = document.getElementsByName( " chkBox " );
for ( var i = 0 ;i < aOpts.length;i ++ ){
if (aOpts[i].checked){
alert( " Checkbox checked and it's value is: " + aOpts[i].value);
}
}
}
function testInput(){
var oInput = document.getElementById( " inpText " );
if (oInput.value == "" ){
alert( " Please input something. " );
} else {
alert( " You input " + oInput.value);
}
}
var aOpts = document.getElementsByName( " chkBox " );
for ( var i = 0 ;i < aOpts.length;i ++ ){
if (aOpts[i].checked){
alert( " Checkbox checked and it's value is: " + aOpts[i].value);
}
}
}
function testInput(){
var oInput = document.getElementById( " inpText " );
if (oInput.value == "" ){
alert( " Please input something. " );
} else {
alert( " You input " + oInput.value);
}
}
<
table
>
< tr >< td > First checkbox </ td >< td >< input type ="checkbox" name ="chkBox" value ="1" /></ td ></ tr >
< tr >< td > Second checkbox </ td >< td >< input type ="checkbox" name ="chkBox" value ="2" /></ td ></ tr >
</ table >
< br >
< input type ="text" id ="inpText" />
< br >
< input type ="button" value ="testSelect" onClick ="testSelect();" />
< input type ="button" value ="testInput" onClick ="testInput();" />
< tr >< td > First checkbox </ td >< td >< input type ="checkbox" name ="chkBox" value ="1" /></ td ></ tr >
< tr >< td > Second checkbox </ td >< td >< input type ="checkbox" name ="chkBox" value ="2" /></ td ></ tr >
</ table >
< br >
< input type ="text" id ="inpText" />
< br >
< input type ="button" value ="testSelect" onClick ="testSelect();" />
< input type ="button" value ="testInput" onClick ="testInput();" />
3.2 操作页面元素
添加元素: document.createElement(tagName);
替换元素: document.replaceChild(oNew,oOld);
添加文本节点:document.createTextNode(text);
添加子节点:appendChild(oElement);
添加HTML: oElement.innerHTML=””;
添加文本:对于IE,用oElement.innerText=”” ,对基于DOM的浏览器,用oElement.textContext=””
元素是否有子元素:oElement.hasChildNode
元素的第n个子元素:oElement.childNodes[n-1]
在以下程序你可以看到这些方法的实际应用:
<
script
type
="text/javascript"
>
function addButton() {
var oDiv = document.getElementById( " btnDiv " );
if (oDiv.hasChildNodes()){
return ;
}
var oInput = document.createElement( " input " );
oInput.type = " button " ;
oInput.value = " NewButton " ;
oDiv.appendChild(oInput);
oDiv = document.getElementById( " txtDiv " );
var oText = document.createTextNode( " add button1 " );
oDiv.appendChild(oText);
alert( " Added button1 " );
}
function addButton2(){
var oDiv = document.getElementById( " btnDiv " );
if (oDiv.hasChildNodes()){
return ;
}
oDiv.innerHTML = " <input type='button' value='NewButton2'/> " ;
oDiv = document.getElementById( " txtDiv " );
if (window.event){
oDiv.innerText = " add button2 " ;
} else {
oDiv.textContent = " add button2 " ;
}
alert( " Added button2 " );
}
function replaceButton(){
var oDiv = document.getElementById( " btnDiv " );
if ( ! oDiv.hasChildNodes()){
return ;
}
var oInput = document.createElement( " input " );
oInput.type = " button " ;
oInput.value = " Replaced button " ;
oDiv.replaceChild(oInput,oDiv.childNodes[ 0 ]);
alert( " I replaced button! " );
}
function removeButton(){
var oDiv = document.getElementById( " btnDiv " );
if ( ! oDiv.hasChildNodes()){
return ;
}
oDiv.innerHTML = "" ;
oDiv = document.getElementById( " txtDiv " );
oDiv.removeChild(oDiv.childNodes[ 0 ]);
alert( " Removed button " );
}
</ script >
< body >
< div id ="btnDiv" ></ div >< div id ="txtDiv" ></ div >
< input type ="button" value ="addButton" onclick ="addButton();" />
< input type ="button" value ="addButton2" onclick ="addButton2();" />
< input type ="button" value ="replaceButton" onclick ="replaceButton();" />
< input type ="button" value ="removeButton" onclick ="removeButton();" />
</ body >
function addButton() {
var oDiv = document.getElementById( " btnDiv " );
if (oDiv.hasChildNodes()){
return ;
}
var oInput = document.createElement( " input " );
oInput.type = " button " ;
oInput.value = " NewButton " ;
oDiv.appendChild(oInput);
oDiv = document.getElementById( " txtDiv " );
var oText = document.createTextNode( " add button1 " );
oDiv.appendChild(oText);
alert( " Added button1 " );
}
function addButton2(){
var oDiv = document.getElementById( " btnDiv " );
if (oDiv.hasChildNodes()){
return ;
}
oDiv.innerHTML = " <input type='button' value='NewButton2'/> " ;
oDiv = document.getElementById( " txtDiv " );
if (window.event){
oDiv.innerText = " add button2 " ;
} else {
oDiv.textContent = " add button2 " ;
}
alert( " Added button2 " );
}
function replaceButton(){
var oDiv = document.getElementById( " btnDiv " );
if ( ! oDiv.hasChildNodes()){
return ;
}
var oInput = document.createElement( " input " );
oInput.type = " button " ;
oInput.value = " Replaced button " ;
oDiv.replaceChild(oInput,oDiv.childNodes[ 0 ]);
alert( " I replaced button! " );
}
function removeButton(){
var oDiv = document.getElementById( " btnDiv " );
if ( ! oDiv.hasChildNodes()){
return ;
}
oDiv.innerHTML = "" ;
oDiv = document.getElementById( " txtDiv " );
oDiv.removeChild(oDiv.childNodes[ 0 ]);
alert( " Removed button " );
}
</ script >
< body >
< div id ="btnDiv" ></ div >< div id ="txtDiv" ></ div >
< input type ="button" value ="addButton" onclick ="addButton();" />
< input type ="button" value ="addButton2" onclick ="addButton2();" />
< input type ="button" value ="replaceButton" onclick ="replaceButton();" />
< input type ="button" value ="removeButton" onclick ="removeButton();" />
</ body >
3.3 创建表格
可以用上述DOM方法来创建表格,也可以用特定的表格方法来进行创建.这些方法包括:
<table/>元素中的方法:
rows:表格中所有行的集合.
deleteRow(position):删除某行.
insertRow(position):插入新行.
<tbody/>中的方法:
rows:表格中所有行的集合.
deleteRow(position):删除某行.
insertRow(position):插入新行.
<tr/>中的方法:
cells:<tr/>元素中所有单元格的集合.
deleteCell(position):删除单元格.
insertCell(position):插入单元格.
演示代码如下:
function createTable(){
var oTable = document.createElement( " table " );
oTable.border = " 1 " ;
oTable.width = " 500px " ;
var oTbody = document.createElement( " tbody " );
oTable.appendChild(oTbody);
oTbody.insertRow( 0 );
oTbody.rows[ 0 ].insertCell( 0 );
oTbody.rows[ 0 ].cells[ 0 ].appendChild(document.createTextNode( " Cell 1.1 " ));
oTbody.rows[ 0 ].insertCell( 1 );
oTbody.rows[ 0 ].cells[ 1 ].appendChild(document.createTextNode( " Cell 1.2 " ));
oTbody.insertRow( 1 );
oTbody.rows[ 1 ].insertCell( 0 );
oTbody.rows[ 1 ].cells[ 0 ].appendChild(document.createTextNode( " Cell 2.1 " ));
oTbody.rows[ 1 ].insertCell( 1 );
oTbody.rows[ 1 ].cells[ 1 ].appendChild(document.createTextNode( " Cell 2.2 " ));
document.body.appendChild(oTable);
}
3.4 性能和文档碎片
当元素添加到document.body或其子元素之后,页面就会自动刷新.如果有大量的添加/删除操作,就有可能引起性能问题.此时就要用到 createDocumentFragment方法,先在文档碎片上进行添加操作,然后一次性添加到document,这样,文档仅刷新一次.
var
arrText
=
[
"
first
"
,
"
second
"
,
"
third
"
,
"
fourth
"
,
"
fifth
"
,
"
sixth
"
,
"
seventh
"
,
"
eighth
"
,
"
ninth
"
,
"
tenth
"
];
var oFragment = document.createDocumentFragment();
for ( var i = 0 ; i < arrText.length; i ++ ) {
var oP = document.createElement( " p " );
var oText = document.createTextNode(arrText[i]);
oP.appendChild(oText);
oFragment.appendChild(oP);
}
document.body.appendChild(oFragment);
var oFragment = document.createDocumentFragment();
for ( var i = 0 ; i < arrText.length; i ++ ) {
var oP = document.createElement( " p " );
var oText = document.createTextNode(arrText[i]);
oP.appendChild(oText);
oFragment.appendChild(oP);
}
document.body.appendChild(oFragment);
3.5 浏览器对象(待续)