一、函数的定义与调用
1、初识函数
函数:用于封装一段完成特定功能的代码。
相当于将一条或多条语句组成的代码块包裹起来,用户在使用时只需关心参数和返回值,就能完成特定的功能,而不用了解具体的实现。
JavaScript“内置函数”的使用
console.log(parseFloat('7.26e-2')); // 返回解析后的浮点数:0.0726
console.log(isNaN(' ')); // 判断是否是NaN:false
console.lD:\桌面\JavaScript总结代码\pro.js
D:\桌面\JavaScript总结代码\JS.htmlog(parseInt('15.99')); // 返回解析后的整数值:15
parseFloat()用于返回解析字符串后的浮点数。
isNaN()判断给定参数是否为NaN,判断结果为是,返回true,否则返回false。
parseInt()用于返回解析字符串后的整数值。
除了使用内置函数外,JavaScript中还可以根据具体情况自定义函数,提高代码的复用性、降低程序维护的难度。
function 函数名([参数1, 参数2, ……]) {
函数体……
}
函数的定义由以下4部分组成:
(1)function:定义函数的关键字。
(2)函数名:可由大小写字母、数字、下划线(_)和$符号组成,但是函数名不能以数字开头,且不能是JavaScript中的关键字。
(3)参数:是外界传递给函数的值,它是可选的,多个参数之间使用“,”分割。
(4)函数体:是专门用于实现特定功能的主体,由一条或多条语句组成。
函数的返回值是在调用函数后若想得到处理结果,在函数体中可用return关键字返回。
注意:函数的名称最好不要使用JavaScript中的保留字,避免在将来被用作关键字导致出错。
2、参数设置
函数可以根据参数的设置分为以下两种:
(1)无参函数:适用于不需要提供任何数据,即可完成指定功能的情况。
function greet() {
alert("qwq");
}
在自定义函数时,即使函数的功能实现不需要设置参数,小括号“()”也不能够省略。
(2)有参函数:适用于开发时函数体内的操作需要用户传递数据的情况。
形参:指的就是形式参数,具有特定的含义,在定义有参函数时设置的参数。
实参:指的是实际参数,也就是具体的值,在函数调用时传递的参数。
function maxNum(a, b) {
a = parseInt(a);
b = parseInt(b);
return a >= b ? a : b;
}
获取函数调用时传递的所有实参:适用于开发时函数体形参不确定的情况。
实现方式:利用arguments对象,在函数体内可获取函数调用时传递的实参。
其他操作:length属性可获取实参的总数,具体实参值可利用数组遍历方式。
function transferParam() {
console.log(arguments.length);
console.log(arguments);
}
含有默认值的参数与剩余参数
函数参数的设置,在ES6中提供了更灵活的使用方式,如设置形参的默认值等。
function greet(name, face = 'qwq') {
console.log( name + face);
}
函数的形参在设置时,还可以为其指定默认值。当调用者未传递该参数时,函数将使用默认值进行操作。
函数定义时,还可用“…变量名”的方式动态接收用户传递的不确定数量的实参。
// 一个确定形参
function transferParam(num1, ...theNums) {
theNums.unshift(num1);
console.log(theNums);
}
// 无确定的形参
function transferParam(...theNums) {
console.log(theNums);
}
3、函数的调用
当函数定义完成后,要想在程序中发挥函数的作用,必须得调用这个函数。
函数的调用只需引用函数名,并传入相应的参数即可。
函数声明与调用的编写顺序不分前后。
函数名称([参数1, 参数2, ……])
[参数1,参数2…]是可选的,用于表示形参列表,其值可以是零个、一个或多个。
4、【案例】字符串大小写转换
代码实现思路:
(1)编写HTML表单,设置两个文本框和两个按钮,文本框显示转换前后数据,按钮用于转换。
(2)为按钮添加点击事件,并利用函数deal()处理。
(3)编写deal()函数,根据传递的不同参数执行不同的转换操作。
(4)将转换后的数据显示到对应位置。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>字符的大小写转换</title>
</head>
<body>
<h1>字符的大小写转换</h1>
原数据:<input id="old" type="text"><br><br>
操 作:
<input type="button" value="转大写" onclick="deal('upper')">
<input type="button" value="转小写" onclick="deal('lower')">
<input type="button" value="求长度" onclick="deal('len')"><br><br>
新数据:<input id="new" type="text">
<script>
function deal(opt) {
var str = document.getElementById('old').value;
switch (opt) {
case 'upper':
str = str.toUpperCase();
break;
case 'lower':
str = str.toLowerCase();
break;
case 'len':
str = str.length;
}
document.getElementById('new').value = str;
}
</script>
</body>
</html>
二、变量的作用域
1、函数内var关键字声明的变量,不能在函数外访问。变量的使用是有作用域范围的。
2、作用域划分:全局作用域、函数作用域和块级作用域(ES6提供的)。
3、不同作用域对应的变量:全局变量、局部变量、块级变量(ES6提供的)。
4、全局变量:不在任何函数内声明的变量(显示定义)或在函数内省略var声明变量(隐式定义)都称为全局变量。
作用范围:它在同一个页面文件中的所有脚本内都可以使用。
5、局部变量:在函数体内利用var关键字定义的变量称为局部变量,它仅在该函数体内有效。
6、块级变量:ES6提供的let关键字声明的变量称为块级变量,仅在“{}”中间有效,如if、for或while语句等。
三、匿名函数
1、函数表达式
函数表达式指的是将声明的函数赋值给一个变量,通过变量完成函数的调用和参数的传递,它也是JavaScript中另一种实现自定义函数的方式。
// 函数表达式
var face = function sum(num1, num2) {
return num1 + num2;
};
face();
// 函数声明方式
sum();
function sum(num1, num2) {
return num1 + num2;
};
2、匿名函数
匿名函数指的是没有函数名称的函数。
作用:可以有效的避免全局变量的污染以及函数名的冲突问题。
说明:既是函数表达式的另一种表示形式,又可通过函数声明的方式实现调用。
(1)函数表达式中省略函数名
var face = function (num1, num2) {
return num1 + num2;
};
face(1, 2);
(2)自调用方式
(function (num1, num2) {
return num1 + num2;
})(2, 3);
(3)处理事件
document.body.onclick = function () {
alert('Hi, everybody!');
};
3、箭头函数
ES6中引入了一种新的语法编写匿名函数,我们称之为箭头函数。
特点:一个箭头函数表达式的语法比一个函数表达式更短。
(p1, p2, …, pN) => { statements }
左边的是参数,右边的是函数体
多个参数:(p1, p2, …, pN)
一个参数:(p1) 或 p1
没有参数:() 或 _
函数体:{ statements }
返回值:{ return expression; }
函数体只有一条语句:expression
// 设置1个参数
var num = x => x + 2;
console.log(num(4));// 输出结果:6
// 设置2个参数
var num2 = (x, y) => x + y;
console.log(num2(1, 2));// 输出结果:3
4、回调函数
回调函数指的就是一个函数A作为参数传递给一个函数B,然后在B的函数体内调用函数A。此时,我们称函数A为回调函数。
匿名函数常用作函数的参数传递,实现回调函数。
在JavaScript中还为数组提供了很多利用回调函数实现具体功能的方法。
方法名称 | 功能描述 |
find() | 返回数组中满足回调函数的第一个元素的值,否则返回undefined |
every() | 测试数组的所有元素是否都通过了回调函数的测试 |
some() | 测试数组中的某些元素是否通过由回调函数实现的测试 |
forEach() | 对数组的每个元素执行一次提供的函数 |
map() | 创建一个新数组,其结果是该数组中的每个元素都调用一次提供的回调函数后返回的结果 |
reduce() | 对累加器和数组中的每个元素(从左到右)应用一个函数,将其减少为单个值 |
reduceRight() | 接收一个函数作为累加器(accumulator)和数组的每个值(从右到左)将其减少为单个值 |
以map()方法为例进行演示,对arr数组中的每个元素都按顺序调用一次回调函数。
var face = ['qwq', 'owo', 'pwp'];
face.map(function (value, index) {
console.log(value, index);
});
参数:map()的参数是一个回调函数fn。
fn的第1个参数表示当前数组的元素。
fn的第2个参数表示对应元素的索引下标。
返回值:回调函数每次执行后的返回值会组合起来形成一个新数组。
示例结果:在控制台依次可查看到,“qwq0”、 “owo1”、 “pwp2”。
四、嵌套与递归
1、函数嵌套与作用域链
嵌套函数:在一个函数内部存在另一个函数的声明。
特点:内层函数只能在外层函数作用域内执行,在内层函数执行的过程中,若需要引入某个变量,首先会在当前作用域中寻找,若未找到,则继续向上一层级的作用域中寻找,直到全局作用域,我们称这种链式的查询关系为作用域链。
2、递归调用
递归调用是函数嵌套调用中一种特殊的调用。它指的是一个函数在其函数体内调用自身的过程,这种函数称为递归函数。
注意:递归调用虽然在遍历维数不固定的多维数组时非常合适,但它占用的内存和资源比较多,同时难以实现和维护,因此在开发中要慎重使用函数的递归调用。
五、闭包函数
1、什么是闭包函数
在JavaScript中,内嵌函数可以访问定义在外层函数中的所有变量和函数,并包括其外层函数能访问的所有变量和函数。但是在函数外部则不能访问函数的内部变量和嵌套函数。此时就可以使用“闭包”来实现。
“闭包”:指的就是有权访问另一函数作用域内变量(局部变量)的函数。它最主要的用途是以下两点:
(1)可以在函数外部读取函数内部的变量。
(2)可以让变量的值始终保持在内存中。
注意:由于闭包会使得函数中的变量一直被保存在内存中,内存消耗很大,所以闭包的滥用可能会降低程序的处理速度,造成内存消耗等问题。
2、闭包函数的实现
闭包的常见创建方式:就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。
function test(){
var x=2;
var y=function(){
return x;
}
x++;
return y;
}
var a=test();
alert(a()); //弹出 3 , y匿名函数只是在当前函数块创建,但是并未执行。函数顺序执行X++后,return y;在此才执行,++过后必然是3而不是2.
六、案例:网页计算器
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>函数的应用</title>
</head>
<body>
第一个数:<input type="text" name="" id="num1"><br/>
第二个数:<input type="text" name="" id="num2"><br/>
操作符号:<button onclick="count('+')">+</button>
<button onclick="count('-')">-</button>
<button onclick="count('*')">*</button>
<button onclick="count('/')">/</button><br/>
结果: <span id="result"></span>
</body>
<script type="text/javascript">
function count(oper){
var num1=parseFloat(document.getElementById('num1').value) //通过id获取节点(元素)
var num2=parseFloat(document.getElementById('num2').value)
var result=document.getElementById('result');
switch(oper){
case '+':result.innerHTML=num1+num2;break;
case '-':result.innerHTML=num1-num2;break;
case '*':result.innerHTML=num1*num2;break;
case '/':result.innerHTML=num1/num2;break;
}
}
</script>
</html>