一、函数基础与种类
1. 函数基础:
- 函数作用:功能的封装、解耦合。
- 函数名命名和变量名规则相同:
a. 不能以数字开头
b. 以字母、$、_开头
c. 不能使用关键字、保留字
d. 语义化、结构化命名
e. 小驼峰命名法:myName()
2. 函数的种类:
函数声明:
/**
* 1. 函数声明:
* 预编译的时候,函数声明会提升,所以函数调用在函数声明前后调用都可以
*/
// 1. 在函数声明前调用:函数声明提升-> function test(){...} -> test();
// test();
function test(){
console.log("函数声明");
}
// 2. 在函数声明后调用
test();
函数表达式:
/**
* 2. 函数表达式:
* 预编译的时候,函数表达式不会提升,所以函数调用要放在函数表达式之后,不然会报错
*/
// test1(); //在函数表达式前面调用函数,报错:Uncaught TypeError: test1 is not a function
var test1 = function test(){
return '函数表达式'
}
test1(); //"函数表达式"
二、 形实参及映射
1. 形实参:
- 形参:函数定义里面的参数;
- 实参:函数调用时传入的参数;
- 形式参个数可以不相等;
- 可以在函数内部修改传入的实参值;
- 实参中未传入值,在函数内部中给形参赋值是无效的,因为给未定义的形参赋值,是undefined;
- 如果形参跟实参是对应关系,那么改变形参的值,实参的值也会跟着改变,它们之间存在映射关系;
function test(a, b, c) { //形参 -> 3个
a = 3;
c = 5;
//arguments[0] <-> a ,形参a重新被赋值为3,所以实参arguments[0]也会跟着改变
console.log(arguments[0]); // 3
//因为实参只有2个,1跟2(arguments[0]、arguments[1]),所以arguments[2]是不存在的
//给未定义的值赋值是undefined
console.log(arguments[2]); // undefined
}
test(1, 2); // 实参arguments: arguments[0] = 1 ; arguments[1] = 2
2. demo:根据输入的实参值,求它们的累加和
function sum() {
var sum = 0;
var _argsLength = arguments.length; // 实参的长度
for (var i = 0; i < _argsLength; i++) {
var idx = arguments[i];
sum += idx;
}
console.log(sum); // 4+5+6=15
}
sum(4, 5, 6)
三、变量类型
1. 全局变量var
- 在全局环境下声明的变量在任何地方都可以访问。
- 在函数内定义变量时省略var操作符,可以创建一个全局变量。只要调用该函数,就会定义这个变量,并且可以在函数外部访问到。
2. 局部变量
- 在函数内部使用var声明变量,它会成为函数的内部变量,该变量在函数执行完后就会销毁。
// 全局变量
a = 1;
function test() {
// 局部变量
var b = 2;
console.log(a, b); // 1 2
// 重新赋值全局变量a a -> 4
a = 4;
function test1() {
// 局部变量
var c = 3;
// 重新赋值test1内的变量b b -> 5
b = 5;
console.log(b); // 5
}
test1();
// test1函数运行完时局部变量c被销毁,所以在外部访问c会报错
console.log(c); // Uncaught ReferenceError: c is not defined
}
test();
四、demo:
4.1 定义一个函数,从window.prompt接收一个饮料的名称,函数返回对应的价格
function drink(name) {
switch (name) {
case '橙汁':
return '¥5';
break;
case '可乐':
return '¥3';
break;
case '雪碧':
return '¥3';
break;
}
}
var name = window.prompt("请输入饮料的名称");
drink(name);
4.2 定义一个函数,从window.prompt接收第一个数,然后一个运算符号(+ - * / %),最后接收第二个数,利用这个函数做运算,并返回运算结果
function compute(value1, type, value2) {
switch (type) {
case '+':
return value1 + value2;
break;
case '-':
return value1 - value2;
break;
case '*':
return value1 * value2;
break;
case '/':
return value1 / value2;
break;
case '%':
return value1 % value2;
break;
default:
console.log('输入格式错误');
}
}
var value1 = Number(window.prompt('请输入第一个数字'));
var type = window.prompt('请输入运算符');
var value2 = Number(window.prompt('请输入第二个数字'));
compute(value1, type, value2);
4.3 定义一个函数,从window.prompt接收一个n,算出n的阶乘,不能用for循环
/**
* !: 阶乘
* n! = n * (n-1)!
*/
function fact(n) {
if (n === 1) {
return 1;
}
return n * fact(n - 1);
}
fact(5);
4.4 定义一个函数,从window.prompt接收一个n,算出斐波那契数列的第n项,不能用for循环
// 递归写法
// 递归:递归总是走到出口的时候,再一步一步向上赋值后返回结果,
// 递归的两个因素:1.找到计算的规律;2.找到出口,让这个递归函数可以结束。
/** 第n的值:n = (n-1) + (n-2) -> 例如第3位: 2 = 1 + 1
* 规律:第1/2位都是1,第3位开始,是它的前两位相加的和,3->2 4->3 5->5...以此类推
* 算出斐波那契数列的第n位:1 1 2 3 5 8 13 21 ...
* n1 n2 n3
* n1 n2 n3
* n1 n2 n3
*/
function test(n) {
if (n <= 0) {
return 0;
}
if (n <= 2) {
return 1;
} else {
return test(n - 1) + test(n - 2);
}
}
var n = parseInt(window.prompt('请输入一个正整数'));
console.log(test(n));