JavaScript简明学习教程
2014年5月31日
目录
一、说明... 2
二、准备知识... 2
(一)HTML. 2
(二)DOM.. 3
三、JavaScript简介... 3
四、JavaScript的运行... 4
五、基本语法... 4
(一)变量... 4
1、变量的声明... 5
2、变量的类型及类型转换... 6
3、变量的作用域... 7
(二)基本数据类型... 9
1、数值类型... 9
2、字符串类型... 9
3、布尔类型... 9
4、undefined和null 10
(三)复合类型... 10
1、Array:数组... 10
2、Object:对象... 11
3、Function:函数... 12
(四)、运算符... 12
1、算术运算符... 12
2、比较运算符... 12
3、逻辑运算符... 13
4、typeof和instanceof运算符... 13
5、其他运算符... 14
(五)语句... 14
1、基本语句... 14
2、流程控制语句... 15
3、特殊语句... 16
六、函数... 18
(一)函数定义及调用... 18
(二)函数参数... 20
七、对象... 23
(一)创建JavaScript对象... 23
1、创建对象增加属性... 23
2、使用对象构造器... 24
3、使用JSON语法创建对象... 25
(二)prototype伪继承... 26
八、事件... 29
九、参考资料建议... 30
一、说明
- 本教程是对JavaScript基本知识点的总结,主要目的是让未学过JavaScript的读者能够少走弯路,快速入门。因此,教程的内容以基本知识点为主,而不在于全,读者读到某部分的知识时要进一步学习或了解的话可以自己上网查阅相关资料(如w3school)。当然,即使你学过JavaScript,也可以拿这个教程当参考资料,因为它对知识点做了较好的总结。
- 后面会举不少例子,对于这些例子,希望读者不要只停留在看的层面上,而是要动手敲代码,自己动手写一遍远比看上三四遍的效果好!切记!
- 对于JavaScript,初学者看到教程的内容这么多,也许会觉得JavaScript难,这里要说的是,千万别那么认为,其实它就是那么回事,要精通它也许有难度,但是要总体掌握它并运用它还是很简单的,只要你投入并动手做。教程之所以有点长是为了说清楚事情的来龙去脉,以让读者更清晰地把握脉络,更好地学习.
二、准备知识
(一)HTML
HTML(Hype Text Markup Language)装逼的叫法叫做网页超文本标记语言,简单地说其实就是一款标记语言——用来描述网页内容的结构以及如何组织如何显示的一种语言,如文字的大小、颜色等。它主要是由一系列的标签组成,其最基本的语法就是<标签名>内容</标签名>。我们在浏览器上看到的形形色色的网页,其实原本都是一个个的HTML文本,浏览器根据文本中的标签等来渲染出我们设计的效果。写网页或设计网页可以说就是根据我们的期望来编辑HTML文本,描述网页的内容和风格。
编辑HTML文档只要一个文本编辑器即可,并不需要什么高端的IDE。(当然,也有一些IDE,如Eclipse、WebStorm等,可根据你的喜好选用,不过,个人觉得没必要)
HTML最基本的结构如下,关于HTML的更多知识请查阅相关资料并总体掌握。
(二)DOM
DOM(Document Object Model)装逼的叫法为文档对象模型,可以理解为一棵树,HTML文档里的元素恰好与树中的节点一一对应。DOM模型提供了访问结构化文档(主要是HTML文档和XML文档)的一种方式,但DOM并不是一种技术,它只是访问结构化文档的一种思想。基于这种思想,各种浏览器都有自己的DOM解析器。
当浏览器装载入一个HTML页面后,浏览器就借助DOM模型,把一个结构化的文档转换成DOM树,这样,程序(如通过JavaScript)可以访问、修改树中的节点,也可以增加、删除树里的节点,在程序操作这棵DOM树时,结构化文档也会相应改变。
如(一)中所述,HTML文档主要就是一系列的元素,当我们要给某个标签指定某种属性,如当要给页面指定背景颜色时,一种做法是在<body>标签中直接指定: <body bgcolor=”blue”>;另一种做法不直接指定,而是通过JavaScript访问该节点并指定属性。后面这种做法更灵活,更方便,而其能这样做的基础就是DOM模型。
三、JavaScript简介
前面说了,HTML是用来描述一个网页的页面的,但是如果只用HTML的话,那么网页的内容都定死了,只能制作成静态(内容固定)的网页,无法完成与客户端动态交互的网页设计。这时,JavaScript就派上用场了。从这里可以看出,JavaScript是一种用来操纵HTML元素的语言。当然,操纵HTML元素的语言还有其他,但JavaScript应该是最基本且应用最广泛的。而之所以能操纵HTML元素,基础就在于前面所述的DOM模型——HTML元素经浏览器解释后对应了一个个的节点,操纵元素就相当于操纵节点。
JavaScript由Netscape的LiveScript发展而来,是一种可以嵌入到页面中的解释性、动态、基于对象的脚本语言。它的主要功能是:动态修改HTML页面内容,包括创建、删除HTML页面元素,修改HTML页面元素的内容,外观、位置、大小等。运行JavaScript的主要环境是各种浏览器。
JavaScript和Java语言在语法上很相似,但它们是两种不同的语言
- Java语言需先经过编译产生字节码然后由Java虚拟机解释执行这些字节码;JavaScript仅仅是一种嵌入到HTML文件中的描述性语言,它并不用编译产生机器代码,而是由浏览器的解释器将其动态地处理成可执行代码。
- 两种语言的变量声明不同。Java是强类型变量语言,所有的变量必须先声明后使用,所有的变量有固定的数据类型;而JavaScript是弱类型变量语言,其变量在使用前无需声明,由浏览器的解释器在运行时检查其数据类型。
四、JavaScript的运行
前面已经介绍了JavaScript通常嵌在网页中执行,在HTML页面嵌入执行JavaScript代码的方式有三种:
- 使用 javascript: 前缀构建执行JavaScript代码的URL
所有可以设置URL的地方都可以使用这种以 javascript: 作为前缀的URL,当用户触发该URL时,javascript: 之后的代码就会被执行
- 使用<script>和</script>元素来包含JavaScript代码
若页面包含大量JavaScript代码,则建议将这些JavaScript脚本放在<script>和</script>标签之间。<script>和</script>成对出现,既可以作为<head…/>的子元素,也可以作为<body…/>的子元素。
示例:
- 为了让HTML页面和JavaScript脚本更好地分离,我们可以将JavaScript脚本单独保存在一个 *.js 文件中,HTML页面导入该 *.js 文件即可。如下:
src指定js文件路径,test.js文件包含的内容示例如下:
五、基本语法
(一)变量
变量是程序设计语言里最重要、最基本的概念,声明变量的作用是确定变量的名字、变量的类型、变量的作用域。
1、变量的声明
JavaScript的变量名与C语言等类似,只能由字母、数字和下划线组成且以字母开头;不能是JavaScript的关键字,如true等,变量命名时最好取见名知义的名字。
JavaScript是弱类型语言,使用变量之前可以先用关键字var定义变量,也可以不先定义直接使用。归纳起来,JavaScript支持两种方式来引入变量:
- 隐式方式:不用事先定义,要使用时直接给变量赋值即可,此时变量被当做全局变量。示例和结果如下:
- 显示方式:用关键字var定义,此时变量被为局部变量。定义时可以同时指定初值,也可以以后在指定。示例及结果如下:
2、变量的类型及类型转换
前面说过,JavaScript是弱类型语言,同一个变量的数据类型不是固定的,可以一会儿存储数值,一会儿存储字符串。示例如下,结果显示为1234:
2.1自动类型转换
JavaScript支持自动类型转换,这种类型转换功能非常强大,示例及结果如下:
- 对于减法运算,因字符串不支持减法运算,故JavaScript会自动将字符串转为数字
- 对于加法运算,因字符串可用加号作为连接运算符,故JavaScript会自动将数字转成字符串拼接。
比较常用的自动类型转换就上面两个,关于更多自动类型转换规则,需要时可上网查阅相关资料。
2.2强制类型转换
虽然知道类型转换方便,但程序可读性差,而且有时候我们希望让字符串和数值进行加法运算,此时需要使用强制类型转换。JavaScript提供了如下几个函数进行强制类型转换:
- toString():将布尔值、数值转成字符串
- parseInt():将字符串、布尔值转成整数
- parseFloat():将字符串、布尔值转成浮点数
需要注意的是:
l 用toString()将布尔值、数值等向字符串转换时,结果全部是object
l 用parseInt()、parseFloat()将各种类型的变量转成数值类型时,若被转换的是数值字符串,则可以转成一个数值,若不是(如字符串含非数字字符或被转换的是undefined、null、布尔值及其他对象)则结果为NaN,表示非数值
示例及结果:
3、变量的作用域
根据变量定义的位置的不同,JavaScript变量有全局变量和局部变量之分。全局变量定义在所有函数体之外,作用范围是整个函数;局部变量定义在函数之内,只对该函
数可见。若全局变量和局部变量名字相同,则局部的覆盖全局的。示例及结果如下:
需要注意的是,
l 与C、Java等语言不同,JavaScript的变量没有块的范围,局部变量在所在的整个函数内有效,而不是在块内。示例如下:
首先,内部的para2屏蔽外部的para2;
其次,虽然内部的para2定义在if块语句内部,但由于局部变量在所在的整个函数内有效,所以局部变量在整个test()函数内有效,在①处时para2已定义,但还没被赋值,故输出undefined;在②处之前,para2被赋值3,所以②处输出3
l 使用var和不用var的区别:
ü 若用var,则程序会强制定义一个新的变量
ü 若不用var,则系统优先在当前上下文中搜索是否存在该变量。只有在该变量不存在的前提下,才会重新定义一个新变量。
例如:如果把上例中③处的var para2=3去掉关键字var,则函数里的para2=3并没有覆盖掉外部的全局变量para2=1,故①输出全局变量值1,③处将全局变量改为3,②处输出新全局变量值3
(二)基本数据类型
JavaScript是弱类型的脚本语言,声明变量时无需指明变量的数据类型,数据类型是解释执行时自动动态决定的。但JavaScript的值保存在内存中时,也是有类型的。其基本数据类型有5种:
1、数值类型
1.1整型:
十进制:var a=12;
八进制:var a=013; //11 (以0开头,只能出现0-7的数字)
十六进制:var a=0x13; //19 (以0X或0x开头,9以上的数字用a-f表示)
1.2实型:
var a=10.10;
var b=2e3; //2000 (科学计数法)
当数值变量的值超过表数范围时,将会得到两个特殊值:Infinity(正无穷大)和-Infinitiy(负无穷大),示例:
var x=1.34245e1234;
var y=-1.2132455e324;
document.writeln(x); //得到 Infiniti
document.writeln(y); //得到 –Infinitiy
相关函数:
isNaN(src):判断src是否是非数值类型,如isNaN(12)//false , isNaN(”sum”)//true
2、字符串类型
JavaScript中没有字符类型,或者说JavaScript中字符类型和字符串类型是完全相同的,用单引号或双引号引起来。
JavaScript中判断字符串是否相等使用==即可,无需使用equals()方法;JavaScript提供的字符串操作的函数很丰富,要使用的话读者可以上网查阅相关资料。
3、布尔类型
只有true和fasle两个值
0,空串为false,其他都是true
4、undefined和null
undefined类型的值只有undefined一个,表示某个变量未定义或已经定义但未初始化
null则表示某个变量已经定义,其值为null
- 若不进行精确比较,则undefined和null本身就相等,即null==undefined为true;若精确区分,则使用精确等于符===。(精确比较运算符,顾名思义,就是不仅值要相等,而且类型也应相同),示例:
例中分支①②③处为true
(三)复合类型
复合类型是由几个基本数据类型或复合类型组成的数据体。JavaScript中的复合数据类型大致分为3类:
1、Array:数组
JavaScript数组的定义的三种语法:
var a=[3,5,23];
var b=[];
var c=new Array();
数组是一系列的变量,JavaScript作为动态的、弱类型的语言,其数组有如下特征:
- 数组长度可变,下标从0开始。通过属性length可以得到元素个数
- 同一个数组中的元素类型可以互不相同
- 访问数组元素时不会产生越界,访问未赋值的数组元素时,值为undefined
示例及结果如下:
2、Object:对象
对象是一系列命名变量、函数的集合,对象中的命名变量称为属性、对象中的函数称为方法。命名变量的类型是基本数据类型或复合类型,对象访问属性和函数的方法都是通过” . ”实现的。如 alert(“浏览器的版本为”+navigator.appVersion); //获得浏览器版本
如前文所述,JavaScript是基于对象的脚本语言,它提供了大量内置对象共用户使用,如:
- Object类:对象类,JavaScript中所有的类都是Object的子类
- Array类:数组类
- Error类:错误类
- Function类:函数类
- Math类:数学类
- Number类:数值类
- String类:字符串类
更多相关知识读者可以上网查阅相关资料。
3、Function:函数
后面详细介绍
(四)、运算符
1、算术运算符
JavaScript支持所有的基本算术运算符,用于执行基本的数学计算,其用法与C语言类似,只是除法运算符 / 不一样,不是取整。主要有:
var a=5;
var b=2;
var c;
加法 +:c=a+b; //7
减法 -:c=a-b; //3
取反 -:c= - c; //-3
乘法 *:c=a*b; //10
除法 /:c=a/b; //2.5 ,注意,不是取整
求余 %:c=a%b; //1
自加 ++:c++; //上步完后c为1,此步自加后为2
自减 --: c--; //1
Math类包含丰富的静态方法,可完成复杂的数学运算:
var a=3.2 , b;
b=Math.pow(a,5); //a的5次方
b=Math.sqrt(a); //a的算术平方根
b=Math.random(); //产生随机数
2、比较运算符
判断两个常量或变量的大小,结果是布尔值,为真返回true,否则返回false。主要有:
- >:大于
- >=:大于等于
- <:小于
- <=:小于等于
- !=:值不相等,
- ==:值相等
- !==:严格不等,若值不等或类型不同,则返回true
- ===:严格相等,若值相等且类型相同,则返回true
说明:
l !=、== 与 !==、===的区别在于是否支持自动类型转换:前两者支持,后两者不支持。由于JavaScript支持自动类型转换,所以5==”5” 为true,5===”5” 为false另两个的区别类似。
l 比较运算符也适用于字符串比较,比较规则为按字母的Unicode值进行比较,如 “abc”>”cde”为false
3、逻辑运算符
用于操作两个布尔型变量或常量,主要有 &&、||、! 三个,用法与其他语言类似。
4、typeof和instanceof运算符
4.1 typeof运算符
typeof ( a ) 用来求得a的数据类型,不同类型参数用typeof后返回值类型如下:
- undefined值:undefined
- null值:object
- 布尔型值:boolean
- 数字型值:number
- 字符串值:string
- 对象:object
- 函数:function
示例及结果:
4.2 instanceof数据类型
instanceof运算符用来判断某个变量是否为指定类的一个实例,若是则返回true,若否则返回false。示例:
结果及分析:
JavaScript中所有的类都是Object的子类,a变量是一个数组,因此两个弹出框都为true。
5、其他运算符
赋值运算符、位运算符、三目运算符等
逗号运算符:整个表达式返回最右端表达式的值,如a=(b=1,c=2,d=3) ; 则a为3
void运算符:强制表达式不返回值,如a=void(b=1,c=2,d=3); 则a为undefined
(五)语句
语句是JavaScript的基本执行单位,JavaScript中的语句以分号(;)结束。
1、基本语句
赋值语句、算术运算语句、逻辑运算语句等,与C等语言类似
2、流程控制语句
2.1、分支
If…else语句 、switch语句,用法与C语言等一样
2.2、循环
for语句、while语句、do…while语句、break和continue,用法与C语言等一样。
for in循环,本质是种foreach循环,主要有两个作用:
l 遍历数组里的所有元素,此时循环计数器为数组索引值,即数组的下标,示例及结果如下:
l 遍历JavaScript对象的所有属性,示例如下:
注:navigator 是浏览器对象,包含了当前使用的浏览器的资料。JavaScript 客户端运行时会自动创建 navigator 对象。运行结果如下:
3、特殊语句
3.1语句块
就是用大括号包含的多个语句,语句块是一个整体的执行体,类似于单独的语句,与C等语言类似。不同的是,虽然JavaScript支持使用语句块,但语句块不能作为变量的作用域。 示例见变量的作用域一节:尽管变量定义在函数内的if块内,但该变量在整个函数内有效。
3.2空语句
仅有一个分号,主要用于没有循环体的循环
3.3异常抛出和捕获语句
JavaScript支持异常处理,支持手动抛出异常,与Java不同的是,JavaScript的异常没有Java那么丰富,JavaScript所以的异常都是Error的对象,当JavaScript需要抛出异常时,总是通过throw语句抛出Error对象。在代码执行过程中,一旦遇到异常,立即寻找对应的异常捕捉块,若没有对应的异常捕捉块,则异常传播给浏览器,程序非正常终止。
l 抛出异常语法:throw new Error(errorString),示例及结果:
l 捕捉异常与Java类似,常用try…catch语句,可以 有finally语句,示例及结果:
归纳起来,JavaScript异常机制与Java异常机制存在如下区别:示例见上例
l JavaScript只有Error一个异常类,无需在定义函数时抛出异常,故无throws关键字
l JavaScript是弱类型语言,故catch语句后括号里的异常实例无需指明类型
l JavaScript只有一个异常类,故try语句块后最多只能有一个catch块
l 获取异常的描述信息是通过异常对象的message属性,而非通过getMessage()方法
3.4 with语句
with语句是一种更简洁的写法,可以避免重复书写对象,语法格式如下:
with(object){ statements }
例如,有如下三条语句:
document.writeln(“line1”);
document.writeln(“line2”);
document.writeln(“line3”);
上述三条语句中,每个语句都有document对象,则可以用with简写为:
with(document)
{
writeln(“line1”);
writeln(“line2”);
writeln(“line3”);
}
六、函数
函数是JavaScript代码复用的单位,它是拥有名称的一系列JavaScript语句的有效组合,只要函数被调用,其内的JavaScript语句就被顺序地解释执行。
(一)函数定义及调用
由于JavaScript是弱类型语言,故定义函数时既不用指明返回值类型,也不用声明参数类型。在同一个<script…/>元素内,JavaScript允许先调用后定义函数,而如果定义和调用不在同一个<script…/>元素内,则不可。
函数有如下三种定义方式,最常用的是前两种:
- 1. 定义命名函数
语法格式:
function functionName(parameter-list)
{
statements
}
示例:如下例中先调用后定义
- 2. 定义匿名函数
大量优秀的JavaScript源码(如Prototype.js、jQuery等)基本都是采用这种方式
语法格式:注意,最后有个分号
var varName= function(parameter-list)
{
statements
};
示例:
上例定义了一个匿名变量,然后把匿名变量赋给变量f,从而运行通过f访问匿名函数。
- 3. 使用Funtion类匿名函数
JavaScript提供了一个Function类,该类也可以用于定义函数,Function类的构造器的参数个数可以不受限制,可以接受一系列的字符串参数,其中构造器的最后一个字符串参数是函数的执行体,执行体的各语句以分号隔开,而构造器最后一个字符串参数前面的各字符串是函数的参数。
但是,这种定义方式很不直观也很不方便,因此很少使用,了解即可。
示例:
上例调用Function类的构造器来创建函数虽然明确地创建了一个Function对象,但由于Function()构造器的最后一个字符串代表函数执行体,但函数执行体语句很多时,最后一个参数将变得很臃肿,故这种定义方法可读性差,很少使用。
(二)函数参数
- 1. 参数传递——值传递
JavaScript的参数传递与Java完全一样,采用值传递的方式:即传入函数里的不是实参本身,而是实参的副本,不管是基本数据类型还是复合类型,都是值传递。(只不过对于复合类型来说,传递的是引用的一个副本,此时传的仍是一个引用)
- 基本数据类型传参示例、结果及分析:
可见,在函数里改变传入的参数值并不影响外面的变量值。
- 复合类型传参示例、结果及分析:
如果仅从person对象的age属性值被改变来看,很多资料、书籍非常容易得出复合类型参数采用引用传递方式的错误结论,然而看上示例子,在changeAge函数里最后将person赋为null,但changeAge函数执行完后,后面的person仍为一个对象,而不是null。
其实JavaScript与Java一样,都是采用值传递的方式。上述程序的关键是,复合类型的变量本身并不持有对象本身,而是该对象的一个引用。因此把person复合类型变量传入函数时,传入的只是person变量的副本——只是该副本和原person变量指向同一个JavaScript对象,因此不管是修改副本所引用的JavaScript对象还是修改原person变量所引用的JavaScript变量,实际上修改的是同一个变量。
- 2. 参数个数
- 与Java或C等语言不同的是,JavaScript并不要求函数调用时的实参个数和函数定义时的形参个数一样,JavaScript将没有传入的实参的参数值自动设置为undefined,示例及结果:
- JavaScript没有所谓的函数重载,对JavaScript来说,函数名就是函数的唯一标识符。当先后定义两个同名的函数,它们的参数列表并不相同时,也不是函数重载,后面定义的将覆盖前面定义的函数。
示例及结果:
- JavaScript对调用函数时输入的参数的个数没有限制。当实参比形参少时,缺少的参数被默认为undefined,当实参个数比形参个数多时,则忽略多余者。这样,就可以使函数接收“可选参数”,实现“重载”。例子:
function power(base,expoent)
{
var result=1;
if(exponent==undefined)
exponent=2;
for(var count=0;count<exponent;count++)
result*=result;
return result;
}
- 3. 函数健壮性
JavaScript和所有弱类型语言一样,由于声明函数时形参无须定义数据类型,故导致调用这些函数时可能出现问题。
例如某个函数的功能是对传入的有5个数的数组的各数求和,当调用时如果传入的是一个整数而不是数组,此时就会出错。
为了解决弱类型语言的这种问题,在函数里使用参数前,应先用typeof方法对参数类型进行判断,只有当是期望的数据类型时才继续。
(三)其他
函数是唯一能创建新作用域的地方:
例:var test=1;
{
var test=2;
}
Alert(test);
大括号语句块并没有创建局部作用域,故改的是全局变量,结果为2
七、对象
JavaScript是一种基于对象的语言,在JavaScript里几乎所有的东西都是对象
JavaScript的对象与Java的Map数据结构类似,由一组键值对key-value组成,其中key为属性,value为值或方法(函数)。JavaScript对象与Java的Map数据结构的不同之处就在于value不仅可以是值,还可以是方法(函数)。
因此,JavaScript的对象简单来看其实就是把一些属性和值或函数封装在一起。
(一)创建JavaScript对象
假定我们把人看成一个对象,有name、age属性和info方法(函数)。至少可以有如下几种创建对象的方式:
1、创建对象增加属性
由于JavaScript是一种动态语言,它允许自由地位对象增加属性和方法,当程序为对象的某个不存在的属性赋值时,即可认为是为该对象增效属性。因此,可以先创建空对象,然后直接通过点”.”的方式添加属性和值。
示例:
结果弹两次框,先后为:
2、使用对象构造器
所谓"构造函数",其实就是一个普通函数,但是内部使用了this 变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。
示例一及结果:
示例二及结果:
当需要访问某个JavaScript对象的属性时,可以使用obj.propName形式或obj[propName]形式,有时还必须使用后面这种形式。
如上例:由于遍历每个属性时循环计数器是属性名,因此必须根据属性名来访问Person对象的属性,若采用p.propName的形式,JavaScript不会把propName当成变量处理,它试图直接访问该名字为“propName”的属性——该属性不存在。
3、使用JSON语法创建对象
各种主流语言都支持JSON数据格式,JavaScript也不例外。
JSON(JavaScript
Object Notation)语法提供了一种更简单的方式创建对象,可以避免书写函数,也可以避免使用new关键字,可以直接创建一个JavaScript对象。为了创建JavaScript,可以使用大括号,然后将每个属性写成“key:value”的形式,key为属性,value为属性值,属性值不仅可以是普通字符串,也可以是任何基本数据类型,还可以是函数、数组,甚至是另外一个JSON语法创建的对象。
例1:
结果:
例2:
结果:
更多详细信息可以上网查阅相关资料。
(二)prototype伪继承
首先,提醒一下:看到标题“prototype伪继承”时不要因为该名词看上去显得高大上而认为这部分内容会很难,其实那只是它装逼的叫法,让人觉得高深。实际上,它的内容很简单,简而言之,就是为了避免内存等资源浪费、为了提高程序的性能,当类中有成员函数时,不直接在类中定义它,而是通过prototype属性(JavaScript中每个对象自己都有prototype属性,一个类也是一个对象)定义它,谨记这点就容易理解了。
下面进入正题。
在上面两个例子中,先定义了一个构造器,在每次通过new方法生成实例时,不仅为实例完成了属性的初始化,而且还为每个实例提供了一个info方法,这样相当不好:一方面,因为每次创建实例时,程序都会为实例提供info函数,当创建多个Person对象时,系统就会有多个info函数——这样会造成系统内存泄漏,,从而引起性能下降,实际上,info函数只需一个就够了;另一方面,会使得info函数中的局部变量产生闭包——即扩大局部变量的作用域,使得局部变量的一直存活到函数之外。
示例:看如下代码,其执行结果为12。由于在info函数里访问了局部变量locVal,导致locVal变量的作用域被放到,在函数外也可以访问到,即形成了闭包。
为了避免这种情况,通常不建议直接在函数定义(也就是类定义)中直接为函数定义方法,而是建议用prototype属性。
伪继承机制——JavaScript的所有类(也就是函数)都有一个prototype属性,我们可以为prototype属性增加属性或函数,此时相当于扩展了原有的类,原有的类不复存在。
示例及结果:
归纳:
JavaScript是一门动态语言,不仅可以为对象动态地增加属性和方法,还可以为类动态地增加属性和方法。
虽然可以在任何时候为类增加属性和方法,但通常建议在类定义结束后立即增加所需方法,以免造成不必要的混乱;同时,应避免在直接在类中定义方法,因为可能造成内存泄漏和产生闭包,而是通过prototype属性来为类增加属性和方法。此外,通过prototype属性为类增加属性或函数时,相当于扩展了原有的类,原有的类不复存在。
八、事件
开头部分说过,传统的HTML只能制作静态页面,引入JavaScript的一个主要目的是为了开发交互式的动态页面,而达到这个目的的一个重要途径就是事件机制。
JavaScript在浏览器中运行,浏览器中的HTML页面主要由DOM组成,这些DOM对象也对应到各种HTML元素,我们就可以为这些DOM对象或HTML元素绑定事件处理函数(或多条JavaScript脚本)当这些DOM对象或HTML元素发生某个动作时,这些事件处理函数就会被触发,从而获得执行的机会。
1、绑定事件
绑定处理函数的方法很多,不同的浏览器的绑定方法也有所区别,通常推荐采用与浏览器无关的事件绑定方法。有两种:
1.1
直接绑定到HTML元素的属性
语法格式为”on事件名=处理方法”
如下例,在input标签里直接绑定点击事件onclick:
这种事件绑定方法简单易用,但绑定事件处理函数时需要直接修改HTML页面代码,因此有几个缺点:
- 直接修改HTML元素的属性,增加了页面的逻辑复杂度
- 开发人员需要直接地修改HTML页面,不利于团队开发
1.2
绑定到DOM对象属性
绑定到DOM对象的属性时,无需修改HTML元素的代码,而是先获得需要绑定事件处理函数的HTML元素对应的DOM对象,然后给该DOM对象的onclick等属性赋值,所赋的属性值是一个JavaScript函数的引用。
如下例,与上例比较,可以看成,事件绑定在JavaScript脚本里进行,而不是在<input>标签上直接绑定
需要注意的是,因为绑定到DOM对象属性时,该属性值只是一个JavaScript函数的引用,因此千万不要在函数后添加括号——一旦添加括号,就变成了调用该函数,于是只是将该函数返回值赋给DOM对象的onclick等属性。
2、事件种类
JavaScript中的事件有很多,主要分为鼠标事件、键盘事件,还有其他一些有用的事件。程序中只要捕获这些事件进行相应的处理,就可以得到我们想要的结果。
- 鼠标事件:
onclick,ondbclick,onmousemove,onmouseover,ondragdrop
onmousein,onmouseout,onmousedown,onmouseup等
- 键盘事件:
onkeydown,onkeyup,onkeypress等
- 其他事件:
onsubmit,onload,onfocus,onblur,onload等
此外,对于不同的HTML标签,支持的事件也不尽相同,如<video>标签就不支持onfocus事件。更多详细知识,读者在要用的时候可以到网上查阅,如w3school:
http://www.w3school.com.cn/tags/html_ref_eventattributes.asp
九、参考资料建议
和其他编程语言一样,关于JavaScript的学习资料浩如烟海,特别是在网上,多如牛毛。这虽然看上去给了我们很大的便利,但有时也给我们的选择造成了很多的困惑——这么多资料该选哪个好?作者当时也遇到了同样的困惑,这里强烈建议读者选择其中一个(一个系列教程或一本书等)跟着一路走到底,这样就会有个总体框架,对JavaScript的各个知识点及其使用有一个基本的了解,也就有了基础!然后就可以投入到项目实践,边做边学,在实践过程中遇到问题时充分利用网络、上网查相关知识或解决办法。
学完本简明教程,一般来说足够让你入门并有不错的基础。当然你也可以选择别的资料,这里推荐几个参考教程或资料:
1、 w3schllo:http://www.w3school.com.cn/js/index.asp