我们开始上课,首先复习一下上节课所讲的内容,上节课我们学习了 JS 的基础语法和JS的原始数据类型以及类型之间的相互转换。
下面来看一下我们这节课的学习任务:一共有四个内容,分别是函数的定义与调用,函数的参数和返回值,函数的嵌套,事件及事件处理。
那接下来我们先看第一个内容,函数的定义与调用,也就是我们首先要知道什么是函数,以及如何用函数。
在代码设计中有一个这样的原则,就是可重复利用,怎么理解呢?就是执行相同功能的代码应该只定义一次。这样就避免了很多不必要的重复,如果说一个功能要重复使用还每次使用就写一段代码实现,那整个代码文件会看起来很长,但是却又好多事重复的地方,大大的增加了代码的冗余度,而且也非常的不好读。所以我们一般都是遵循这个原则的。因此就有了函数的定义,在数学中,函数是这样的,给它传递一个 x 值,就会对应的得到一个 y 值,其实函数定义的是一种特定的运算规则。相似的,在编程中,函数是一段完成特定功能的代码。它有这样两个特点,一个是可重用性,还有一个就是任务分解。把任务分块化,模块化,让任务更高效的完成。
那一个函数有三个要素,分别是函数名,函数的参数,函数的返回值。这个额很好理解了,函数名,比如 alert
,parseint
这些,如果没有函数名的话,它就和一段普通的程序段没有什么区别,也不能被重复使用了,为什么?因为没有名字啊,你不知道实现这个功能该传唤谁呀,就像我们人一样,如果大家都没有名字,那还怎么好好工作好好交流啦?那没法交流啊,说你这样,你那样,可是“你”又是谁啊?“你”谁都可以是。函数的参数,是什么呢?是传递给函数名的值,代表将被函数处理的数据。大家想,如果没有这个参数的话,那这个函数有没有重复利用的价值呢?到了该输入 2 了,它却输出的是3的结果,这让我们情何以堪呢?比如 alert
函数,我们想弹出 hello,结果它弹出的是 bye。是吧,函数他之所以有可重复使用性,就在于,它在运算规则不变的情况下是可以变化的,是可以接受变量的。如果你总是想得到这段代码的结果,完全不变的结果,那你完全没有必要写一个函数呀,既然结果是已知而且不变的,直接写上那个就好了,直接赋值给一个变量就可以了,没有必要新增一个函数的功能啊。最后一个要素就是返回值,也就是函数执行的返回结果。比如 confirm()
函数,他的返回值就是 true
或者 false
。这也不难理解,如果我们不要结果,那你放在那儿还有什么意义,什么作用呢?就像我们人活着要有人生价值一样,那段代码放到那儿也是要是代码价值的,要不然它还有什么存在的必要性啊?就没有了。
好,下面我们来看一下JS中的函数,在 JS 中呢,函数分为两类,一类是 JS 内置函数,还有一类是自定义函数。JS内置函数,这个很好理解,就是 JS 已经定义好的,现在已经存在的,可以用的函数,比如:parseint()
,alert()
,confirm()
等,这些不需要我们再去写代码段定义了,不用我们自己去造的函数就是JS的内置函数,那明白了内置函数的概念就好理解自定义函数了,显然就是自己定义的,自己编写的函数。这种函数就要在具体的代码文件中,在上下文的环境中去分析函数的功能,从而写出函数。
那内置函数是现有的,自定义的又该怎么定义呢?我们一起来看一下。函数的定义一共有两种,一种是规规矩矩的,用 function
关键字来定义函数,如课件上展示的那样。好,下面我们来看一个示例。 示例 1-3-1。我们先来读一下这段代码,首先我们看到这段代码是相当的工整,缩进得当,注释合理,以后我们写代码的时候也要注意写的整齐美观,这样是不是我们读起来就快很多?可以很清晰的看出代码结构,从而可能在代码功能上更容易理解。下面我们来解读一下这段代码吧,不长。首先声明了三个变量,它们的注释是:取得表单数据。大家看这是什么变量?全局变量,为什么?因为它们不是在函数中声明的,函数体是途中红色框框中的部分,我们可以读出,这是一个检验输入值长度的函数,如果长度小于四,那么就会提示长度不够。下面是三个调用函数的命令,很显然就是直接调用的,什么别的关键字都不用再添加了。下面我们来运行一下这个示例。函数的另外一种定义方法是用函数直接量定义函数,这种情况是匿名函数。我们看匿名函数一共有下面三种定义方式,首先第一种,定义好就要马上执行的,因为没有办法认为控制调用,就只能定义完成就是该调用的时候了。第二种是把函数赋值给了一个变量,那这个变量的值就是这个函数运行的结果。第三种是把函数赋值给了一个事件,和赋值给一个变量类似,就是在这个时间发生的时候就执行这个函数。
下面我们来看一下函数的调用,把函数定义好就是为了以后可以用的,所以一定要会调用函数。函数的调用呢一共有三种方式,这也很好理解,一种是直接调用,就是用函数的名字加()运算符直接调用,调用的时候如果咱们的函数有参数,还要向函数传入参数,函数还有可能有返回值。第二种是在表达式中调用函数,也就是像这样,那 sum 的值就是 add
函数计算的结果。第三种是在事件中调用,也就是当某个事件发生的时候,JS会调用函数来响应这个事件。
下面我们来看一下当调用函数是,JS 程序的执行过程是怎样的,我们知道,JS程序是自上而下执行的,当遇到函数调用的时候,就会跳转到函数定义的地方,执行函数,函数执行完再继调用函数之后接着执行后面的代码。这个过程应该是很好理解的对吧,其实就是用一个函数名字代替一段代码,调用这个函数,就是把函数名的地方替换成函数体中的程序块。
我们可能听说过,函数式编程这个说法,那什么是函数式编程呢?也就是函数在整个编程过程中是普遍存在的,是应用方便的。函数像一个普通变量一样可以赋值给其他变量,可以作为参数传递,也可以作为函数的返回值返回。我们可以通过一个例子来看一下,看一下 示例 1-3-3.
好了,下面我们来看一下试用函数时的一些注意事项。首先定义函数是,函数名要是合法的标识符,什么事合法的标识符?不能使用关键字和保留字,最好可以通过函数名看出函数的功能。第二,设计函数时,最好每个函数只能实现一种功能,这样有利于函数的扩展,引用和维护。第三,为了方便引用呢,常用的或者先用的函数应该放在整个 JS 代码的前面。
好了,下面我们来看下一个小问题,函数的参数和返回值。我们刚刚讲了函数的三要素还记得吧?函数名,函数的参数和函数的返回值那现在咱们就来看看这函数的参数和返回值都有什么门道?函数参数的概念大家在之前的学习中应该都已经学习过了,下面我们看,在定义函数时,有时候会给函数定义参数就是写在这儿,需要几个写几个,在调用的时候要输入参数,我们才能得到相应的函数值啊。这就和数学中的函数很相似了,看这里有两个概念,一个概念是形式参数,也就是形参,还有一个是实际参数,也就是实参,这些概念应该在数据结构中都学习过了,我想大家应该知道是什么意思,这形参啊,就像是数学中函数的变量一样,它只是一个标记符号,不是一个具体的可以计算的数值。而实参,是在调用时输入的,是某个变量的值,是一个实际的值,其实是一个定量。下面通过例子我们来认识一下形参和实参,以及参数的一些特点。首先我们看,图中已经标出的在定义函数是的 text
和 size
是形参,而下面调用函数是输入的 “J” 和 “20px” 是实参。还有下面的那个也是一样的。
需要注意的一点是,在定义函数是使用了多少个形参,在该函数调用的时候就要给出相同数目的实参。多个参数之间要用 , 隔开,在函数体重,形参就是一个变量,使用多个参数是,调用所给出的各个实参按照其排列的先后顺序依次传递。像这个例子中所写的那样,我们定义了求和函数 sum
,它有两个参数,那下面我们调用的时候有写一个参数,或者写三个参数,多写一个,我们看一下会是什么样的执行结果呢?
好了,下面来看一下函数的返回值,在函数调用时,一方面可以输入数据,另一方面呢还可以从函数获得数据,也就是函数运行的结果啦。看下面这个示例,这是定义了一个比较大小的函数,输入两个参数,结果会输出两个数中较大的一个,在函数体中用了返回关键字 return
,我们运行一下看看。
下面来看一下返回值都有哪些习惯?首先返回值可以直接赋给变量或用于表达式中。然后呢return
语句表示结束当前函数的执行,也就是执行到return
的时候,函数就会结束执行,返回想要返回的值就可以了。然后呢,return
语句可以不带表达式,例如直接写一个return
,而这样返回的值就是undefined
。然后是函数中可以不出现return
语句,也就是return
不是函数必备的语句,不出现返回值的时候,仍会返回值,该值也同样是undefined
。
好,下面我们来看一下函数使用的一些注意事项吧。函数名,上一小节也强调过了,要有一定的意义,便于读取和理解。不可以使用关键字和保留字。函数的位置,函数通常放在JS代码的开头,方便后续引用。函数的次序,常用函数和首先使用的函数放在前面。参数类型,函数定义,不要为参数提供数据类型,本来JS就是弱类型的,所以提前声明类型也是没有必要的。函数返回数据类型,函数返回值可以是任意类型的数据,所以也不需要显示设置返回类型。
好,看下面我们来看一下第三小节的内容,函数的嵌套。在一个函数定义的函数体语句中出现了对另一个函数的调用,这就是函数的嵌套调用。注意,在一个函数调用另一个函数的时候,应该提前定义好被调用的函数,就像下面这样,在second
函数中调用first
函数,看以下这个示例。
那讲到嵌套了,我们就来说说变量作用域的问题。在JS中,变量分为两种,一种是全局变量,一种是局部变量。什么事全局变量呢?啊,在所有函数之外定义,或者是没有通过var关键字定义的变量,其作用范围是同一个页面文件中的多有脚本,所以它叫做全局变量。那显然局部变量就是通过var定义且在函数体中定义的变量,是局部变量,而且它的作用于就是该函数体。同名变量在不同的函数体中是不会相互冲突的,而在同一个页面的不同的JS文件中,恰好都使用了同名的全局变量,就会造成相互影响,产生难以调试的错误。我们来看一个例子,了解一下。
下面我们来看最后一小节,事件及事件处理。
事件,能够被JS检测到的活动。一般有两种情况,一种是用户的动作,比如:鼠标点击或者是键盘操作。还有一种是状态的变化,比如:加载或者改变文本框的内容,页面加载完成等。从字面的也很好理解,事件嘛,就是一件事情。事件处理函数也就是当该活动发生时,称之为触发事件时,所执行的响应该活动的函数。下面看一个单击事件的例子。看这段代码,嘚嘚嘚嘚嘚。。。
下面我们来系统的了解一下事件,首先看一下事件的三要素:在哪个HTML标签上,也就是在哪里起作用,发生什么事件?也就是事件本身。还有就是程序作何处理,也就是事件处理函数是啥。发生了这个事件会做什么?会怎样?比如你点击了一个按钮,会怎么?是会弹出一个对话框?还是会进行一个运算?还是会返回?会下一步?等等。
那怎么用呢?一切的理论都是服务于实践的,我们看一下如何添加事件。在JS中,为元素添加一个事件,一般有两种方法,一是在HTML元素中,添加HTML动作属性,绑定一个事件处理函数。如下面的这段代码,在input
按钮上面加上一个事件点击,当点击的时候会调用事件处理函数calculate()
。相当于在HTML标签上给它添加一个触发事件的属性。还有一种方法是在JS中,为HTML元素动态添加事件处理函数。如下面的代码,当window
窗口加载完成后调用后面的函数。
事件处理机制,就是当某一个事件触发时,会执行操作以响应该事件;当该事件再次发生时,响应操作会再次执行。响应事件的操作是一段代码,会捕获每一次事件触发的动作,然后执行该段代码。即事件处理机制中,函数的执行是由事件所触发的。
下面看一些常用的事件类型,onload
,是页面加载事件,在页面或图像加载完成后立即发生。onunload
事件,是页面推出事件,在用户退出页面是发生。onabort
,图片事件,在图像加载被中断时发生。表单事件。在下面的这个表格里,我们把他们翻译成中文来看。onblur
:当前元素失去焦点时触发,鼠标或者键盘均会触发。onchange
:当前元素失去焦点并且元素的内容发生改变而触发(鼠标与键盘均会)。onfocus
:当某个元素获得焦点时触发。onreset
:当表单中reset
的属性被激发时触发。onselect
:当文本框中的文本被选中时触发。onsubmit
:当表单被提交时触发。
还有一些键盘和鼠标事件。我们先来看翻译的,翻译的没有原文给的多,一会儿咱们再回去看原文的。onkeydown
:当用户按下一个键盘按键时触发。onkeypress
:在键盘按键被按下并释放一个键时触发。onkeyup
:在键盘按键被松开时触发。onclick
:在对象被点击时触发。原文中还有:ondblclick
:当被双击时;onmousedown
:当鼠标点击的时候触发 (这里有英文待考究)
最后说一下事件在JS中的地位,JS程序是基于事件驱动的,因为它是通过事件同用户进行交互的,一般情况下初始化的代码都会在文档加载事件中执行。