八、初识函数
1.定义
function 是定义函数的关键字,函数也称为方法 。
函数分为:1.无参函数 2.带参函数 3.带返回值的函数
定义函数
function fn(形参) {
方法体
}
调用函数
fn(实参)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>函数</title>
</head>
<body>
<script>
// 函数,也称之为方法,是完成某个功能的代码块
// function 是定义函数的关键字
// 函数分为:1.无参函数 2.带参函数 3.带返回值的函数
//1.定义无参函数,函数的()里面没有定义参数,这样的函数就是无参函数
function fun1(){
let num1 = 100
let num2 = 200
console.log(`${num1}+${num2}=${num1+num2}`);
}
// 函数必须要调用后,才会执行里面的代码
fun1()
console.log('----------------------------');
//2.定义带参数函数,函数的()里面需要传参数,参数可以传多个,参数名是自定义的
// 函数在定义时候,定义的参数是:形参
function fun2(num1,num2){
console.log(`${num1}+${num2}=${num1+num2}`);
}
// 带有带参数的函数时,传递具体的实际值(函数在调用时,传递的参数是:实参)
fun2(100,200)
fun2(1000,2000)
fun2(10,20)
// 调用带参数的方法时,如果没有传递参数,那么参数就是值就是undefined
fun2()
console.log('----------------------------');
// 3.带返回值的函数
function fun3(num1,num2){
let sum = num1 + num2
// return关键字,只能用的函数中,用于返回函数的执行结果
return sum
}
// 调用带返回值的函数,需要通过变量接收函数的返回值。
let sum = fun3(100,200)
console.log(sum);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>函数练习</title>
</head>
<body>
<!-- 导入外部js -->
<script src="./js/$a.js"></script>
<script>
//创建一个当前日期
let date1 = new Date()
//创建一个指定日期
let date2 = new Date('2020-1-1 12:8:8')
//根据时间戳创建一个日期对象
let date3 = new Date(123234214213)
console.log(formatDate(date1));
console.log(formatDate(date2));
console.log(formatDate(date3));
console.log('-----------------------------');
let arr1 = [11,66,33,245,7,99]
let arr2 = [77,234,5,66,28]
mySort(arr1)
mySort(arr2)
console.log(arr1);
console.log(arr2);
</script>
</body>
</html>
2.实现字符串函数
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>手写实现字符串的函数</title>
</head>
<body>
<script>
// 定义一个函数:获取一个字符串指定下标的字符
let str1 = 'abcdefg'
function charAt(index){
return str1[index]
}
console.log(charAt(3));
console.log('-----------------------------');
// 定义一个函数:返回字符串中指定字符第一次出现的位置
let str2 = "abc你def你gwt你zyt"
function indexOf(str){
let index = -1 //定义一个变量,用于表述字符串的位置
//循环出字符串中所有的字符串
for(let i=0;i<str2.length;i++){
//挨个比较字符串中所有的字符
if(str2[i]===str){
//如果相对,就返回对应的下标
index = i;
break;
}
}
return index
}
console.log(indexOf('你'));
console.log(indexOf('好'));
console.log('-----------------------------');
// 定义一个函数:返回字符串中指定字符最后一次出现的位置
function lastIndexOf(str){
let index = -1 //定义一个变量,用于表述字符串的位置
//循环出字符串中所有的字符串
for(let i=str2.length-1;i>=0;i--){
//挨个比较字符串中所有的字符
if(str2[i]===str){
//如果相对,就返回对应的下标
index = i;
break
}
}
return index
}
console.log(lastIndexOf('你'));
console.log(lastIndexOf('好'));
console.log('-----------------------------');
// 定义一个函数:用于截取指定区间范围内的字符串,如果只传一个参数,从起始位置往后全部截取
let str3 = 'abcdefghijklmn'
function substring(index1,index2){
let str = "" //定义一个变量,用于保存截取的结果
//如果index2没有值,截取到最后
if(!index2){
index2 = str3.length
}
//确定循环的范围
for(let i=index1;i<index2;i++){
str+=str3[i]
}
return str
}
console.log(substring(3,7));
console.log(substring(3));
console.log('-----------------------------');
// 定义一个函数:用于截取指定长度的字符串,第一个参数是位置,第二参数是长度
function substr(index,len){
let str = "" //定义一个变量,用于保存截取的结果
//确定查找范围
let index2 = index+len
//如果len是空,那么就从起始位置到最后全部截取
if(!len){
index2 = str3.length
}
//确定循环的范围
for(let i=index;i<index2;i++){
str+=str3[i]
}
return str
}
console.log(substr(3,7));
console.log(substr(3));
console.log('-----------------------------');
</script>
</body>
</html>
3.实现数组的函数
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>手写实现数组的函数</title>
</head>
<body>
<script>
// 手写一个数组函数:用于从数组中检查指定的数据是否存在,存在返回true,不存在返回false
let arr1 = [25,66,3,46,38]
function includes(val){
let isFind = false //定义一个变量,用于表示是否找到
//循环数组
for(let i=0;i<arr1.length;i++){
//判断数组中的每一个元素
if(arr1[i]==val){
isFind = true
break //加上这个break,可以提高性能
}
}
return isFind
}
console.log(includes(33));
console.log(includes(88));
console.log('-------------------------');
// 手写一个数组函数:用于将一个数组根据某个字符串拼接成字符串,该方法不传参数,默认是根据逗号拼接
function join(str){
let str1 = "" //定义一个字符串,用于拼接
//如果str是空,赋值为逗号
if(!str){
str=","
}
//拼接数组最后一位前面的所有数据
for(let i=0;i<arr1.length-1;i++){
str1+=arr1[i]+str
}
//最后再拼接数组的最后一位
str1+=arr1[arr1.length-1]
return str1
}
console.log(join('你好'));
console.log(join());
console.log('-------------------------');
// 手写push
function push(val){
//增加一个数组空间,存储数据
arr1[arr1.length] = val
}
push(66)
console.log(arr1);
push(77)
console.log(arr1);
console.log('-------------------------');
// 手写pop
function pop(){
//重新设置数组的长度,会去掉最新长度后面的元素。
arr1.length = arr1.length-1
}
pop()
console.log(arr1);
console.log('-------------------------');
// 手写unshift
function unshift(val){
//从后往前循环整个数组
for(let i=arr1.length-1;i>=0;i--){
//将数组里面原始数据完后挪一个位置
arr1[i+1] = arr1[i]
}
//再将添加的元素,放到数组的第一位
arr1[0] = val
}
unshift(123)
console.log(arr1);
console.log('-------------------------');
// 手写shift
function shift(){
//循环整个数组,将数组中的后一位数,覆盖前一位数
for(let i=0;i<arr1.length-1;i++){
arr1[i] = arr1[i+1]
}
//再删除掉最后一位数
arr1.length = arr1.length-1
}
shift()
console.log(arr1);
console.log('-------------------------');
// 手写reverse
function reverse(){
//算出比较的次数(6个数比较3次,7个数也是比较3次)
let count = Math.floor(arr1.length/2)
//循环比较的次数
for(let i=0;i<count;i++){
//将前面的数,通过一个中间变量保存
let temp = arr1[i]
//将后面的数赋值给前面的数
arr1[i] = arr1[arr1.length-1-i]
//再将中间变量的值,赋给后面的数
arr1[arr1.length-1-i] = temp
}
}
reverse()
console.log(arr1);
</script>
</body>
</html>
4.定义函数的几种方式
1.第一个方式:通过function关键字直接定义
2.第二种方式:定义一个变量,接收定义的函数
3.ES6又推出了定义函数的简写方式,俗称:箭头函数
(1).在箭头函数中,如果方法体只有一条语句,可以省略{}
(2).在箭头函数中,如果方法只有一个参数,可以省略()
(3).在箭头函数中,如果方法体只有一条语句,并该语句是返回语句,那么在省略{}的同时,必须省略return关键字
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>定义函数的三种方式</title>
</head>
<body>
<script>
// 第一种方式:通过function关键字直接定义
function fun1(){
console.log('我是方法一');
}
fun1()
// 第二种方式:定义一个变量,接收定义的函数
let fun2 = function(){
console.log('我是方法二');
}
fun2()
// 第三种方式:箭头函数,其实就是第二种方式的简写。(ES6新推出的一种方式)
let fun3 = ()=>{
console.log('我是方法三');
}
fun3()
console.log('-----------------------------------');
/* let fun4 = (num1,num2)=>{
return num1 + num2
} */
// 如果箭头函数的函数体,只有一条语句,可以省略大括号,如果这一条语句还是返回语句,return关键字必须省略
let fun4 = (num1,num2)=>num1 + num2
console.log(fun4(100,200));
let fun5 = (num1,num2)=>console.log(`${num1}+${num2}=${num1+num2}`);
fun5(100,200)
// 如果箭头函数的参数,只有一个,那么可以省略小括号
let fun6 = num=>console.log(num*3);
fun6(100)
// 如果箭头函数没有参数,通常要保留小括号,如果非要去掉小括号,需要写一个下划线占一个位置
let fun7 = _=>console.log('我是箭头函数')
fun7()
</script>
</body>
</html>
5.定义几个工具方法
1.检查一个年份是否是闰年
2.对个位数字补零
3.返回一个日期的短日期格式
4.返回一个中国式的日期格式
5.对字符串反转
外部javascript代码:
// 判断是否是闰年的方法
let isLeapYear = (year) => (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
// 对个位数字补零的方法
let repair0 = (val) => (val < 10 ? "0" + val : val);
// 返回一个日期的短日期格式方法
let miniDate = (date, type) => {
let year = date.getFullYear(); //年
let month = date.getMonth() + 1; //月
let day = date.getDate(); //日
let hour = date.getHours(); //时
let minute = date.getMinutes(); //分
let second = date.getSeconds(); //秒
let week = date.getDay(); //周几
//定义一个返回值,默认拼接:年,月,日
let ret = [repair0(year), repair0(month), repair0(day)].join("-");
if (type == "1") {
ret += " " + [repair0(hour), repair0(minute), repair0(second)].join(":");
} else if (type == "2") {
ret +=
" " +
[repair0(hour), repair0(minute), repair0(second)].join(":") +
" 星期" +
"日一二三四五六"[week];
}
return ret;
};
// 对字符串反转的方法
let reverseStr = (str) => str.split("").reverse().join("");
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>定义几个工具方法</title>
</head>
<body>
<script src="./js/$a.js"></script>
<script>
console.log(isLeapYear(2000));
console.log(isLeapYear(2003));
console.log('------------------------');
console.log(repair0(15));
console.log(repair0(5));
console.log('------------------------');
console.log(miniDate(new Date()));
console.log(miniDate(new Date(),'1'));
console.log(miniDate(new Date(),'2'));
console.log('------------------------');
console.log(reverseStr('abcdefg'));
</script>
</body>
</html>
6.递归方法
什么是递归方法:就是一个方法,自己调用自己。注意:递归方法,一定要控制好合适跳出,否则就是死循环
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>递归方法</title>
</head>
<body>
<script>
// 什么是递归方法:就是一个方法,自己调用自己
// 注意:递归方法,一定要控制好何时跳出,否则就是死循环
// 经典面试题:使用递归算法1-20之间所有数之和
function calc(num){
//这个if是退出递归的条件
if(num===1) {
return num
}
return num + calc(num-1)
}
console.log(calc(1));
console.log(calc(2));
console.log(calc(3));
console.log(calc(20));
</script>
</body>
</html>
实现系统菜单
function menu(){
let no = parseInt(prompt('1.添加学生,2.修改学生,3.删除学生,0.退出系统'))
switch(no){
case 1:
alert('执行添加学生')
menu()
break;
case 2:
alert('执行修改学生')
menu()
break;
case 3:
alert('执行删除学生')
menu()
break;
default:
return //表示退出方法
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>递归方法的实际应用</title>
</head>
<body>
<script>
// 实现系统菜单
function fun1(){
let menu = 0
do{
menu = parseInt(prompt('1.添加 2.修改 3.删除 4.查询 0.退出'))
switch(menu){
case 1:
alert('执行添加')
break;
case 2:
alert('执行修改')
break;
case 3:
alert('执行删除')
break;
case 4:
alert('执行查询')
break;
default:
alert('欢迎下次继续使用');
break;
}
}while(menu!==0)
}
// fun1()
function fun2(){
let menu = parseInt(prompt('1.添加 2.修改 3.删除 4.查询 0.退出'))
switch(menu){
case 1:
alert('执行添加')
fun2() //在方法内部,又重新调用自己
break;
case 2:
alert('执行修改')
fun2()
break;
case 3:
alert('执行删除')
fun2()
break;
case 4:
alert('执行查询')
fun2()
break;
default:
alert('欢迎下次继续使用');
break;
}
}
fun2()
</script>
</body>
</html>