一、函数基础与种类

image.png
数学函数:输入x 得出y
函数式编程:用函数封装功能模块,代码复用,解耦合
image.png
三种情况想完成一个功能,其实是一个功能
这就有耦合的情况,重复代码块太多了
高内聚低耦合,让代码块重复更少
解耦合,函数一般比较常用

=> 等同于的意思

耦合 : 重复的代码太多了,代码的重复度太高了
高内聚:强功能性,高独立性
低耦合:把重复的代码提取出来 -> 模块的单一责任制
解耦合:使用函数可以很好的进行解耦合(减少重复)

最基本的函数写法 - 函数

  1. function test (参数){
  2. 函数执行语句
  3. }

函数名的命名规则
不能数字开头
字母 数字 下划线 $ 组成
小驼峰命名法 myFunction

函数作用:功能的封装、解耦合。
函数名命名和变量名规则相同。
定义函数的语法:

  1. // 函数声明的方式定义
  2. function name(arg1, arg2) {
  3. ...
  4. }
  5. // 函数表达式的方式定义
  6. //匿名函数表达式 函数字面量
  7. //匿名函数
  8. var name = function (arg1, arg2) {
  9. ...
  10. }
  11. var name = function name2(arg1, arg2) {
  12. ...
  13. }
  14. //name2可以省略
  1. var test = function test1() {
  2. var a = 1,
  3. b = 2;
  4. // 可以在函数内部调用test1()
  5. console.log(a, b);
  6. }
  7. // 如果是匿名函数,则打印test
  8. console.log(test.name); // 'test1'
  9. test(); // 1 2

函数只有被调用时才会执行,不调用时不会

二、形实参及映射

function 函数名 参数(可选) 返回值(可选) return代码自动在后面加上,没有返回值返回undefined

2.1 形实参

2.1.1 形参


函数定义里面的参数。
占位->形式上占位,形式参数 形参

2.1.2 实参


函数调用时传入的参数。
实际参数 实参
image.png
false NaN
什么数据类型都可以传过去

  1. var aa = Number(window.prompt('a'));
  2. var bb = Number(window.prompt('b'));
  3. // a, b 形参
  4. function test(a, b) {
  5. console.log(a + b);
  6. }
  7. // aa,bb 实参
  8. test(aa, bb);

image.png
形参实参,形参是占位符
实参只有在test(aa,bb)函数运行时的赋予的值,aa、bb都是实参
a、b以及函数里面的都是形参,因为函数不运行,不知道传入的是什么参数,所以用形参来占位指代,相当于f(x)=2x的x,指代要传入的值

2.1.3 形式参个数可以不相等

image.png
不会报错
image.png
image.png
1 2

  1. function test(a, b) {
  2. // 函数形参个数
  3. console.log(test.length); // 2
  4. // 函数实参个数
  5. console.log(arguments.length); // 3
  6. }
  7. test(1, 2, 3);

2.2 arguments


1.类数组对象。
2.存储实参列表。
3.可以在函数内部修改传入的实参值。
4.实参未传入时,在函数内部给行参赋值无效。
image.png
image.png
image.png
在函数内部可以更改实参的值,

image.png
undefined
没有声明b,b是undefined,没有声明,不能赋值,所以arguments[1]是undefined
image.png
argument[0]与a不是一个东西,存储地方不同,但有映射关系
a=3 a存栈内存里,argument[0]存堆内存里
实参与形参是不同的量,存在不同的地方,但是系统里有映射关系,无论实参怎么赋值,形参都会改变,但一定形参数组里面有对应的值才行,如果没有对应的值没有用,有映射关系,给形参赋值实参也会改变
参数有没有映射关系看一开始函数运行时给他赋予参数了没有,即使是undefined也行,不写写个,不行

  1. function test(a, b, c) {
  2. a = 3;
  3. c = 5;
  4. console.log(arguments[0]); // 3
  5. console.log(arguments[2]); // undefined
  6. }
  7. test(1, 2);
  1. function test(a, b, c) {
  2. arguments[0]=6;
  3. console.log(a)//6
  4. a = 3;
  5. c = 5;
  6. console.log(arguments[0]); // 3
  7. console.log(arguments[2]); // 5
  8. }
  9. test(1, 2,undefined);
  1. function test(a, b, c) {
  2. arguments[0]=6;
  3. console.log(a)//6
  4. a = 3;
  5. c = 5;
  6. console.log(arguments[0]); // 3
  7. console.log(arguments[2]); // undefined
  8. }
  9. test(1, 2,);

2.3 return语句


1终止函数执行
2返回相应的值
image.png

  1. function test(name) {
  2. return name || '你没有填写姓名';
  3. }
  4. console.log(test()); // '你没有填写姓名'

根据输入实参,求累加和

  1. // 一个函数被调用时,累加它的实参值
  2. function sum() {
  3. var _length = arguments.length;
  4. var sum = 0;
  5. for (var i = 0; i < _length; i++) {
  6. sum += arguments[i];
  7. }
  8. console.log(sum);
  9. }
  10. sum(1, 2, 3);

三、变量类型

3.1 全局变量


1.在全局环境下声明的变量在任何地方都可以访问。
2.在函数内定义变量时省略var操作符,可以创建一个全局变量。只要调用一次该函数,就会定义这个变量,并且可以在函数外部访问到。

3.2 局部变量


使用var操作符定义的变量会成为包含它的函数的局部变量,该变量将在函数退出时销毁。

  1. // 全局变量
  2. a = 1;
  3. function test1() {
  4. // 局部变量
  5. var b = 2;
  6. console.log(a, b); // 1 2
  7. // 重新赋值全局变量a a -> 4
  8. a = 4;
  9. function test2() {
  10. // 局部变量
  11. var c = 3;
  12. // 重新赋值test1内的变量b b -> 5
  13. b = 5;
  14. console.log(b); // 5
  15. }
  16. test2();
  17. // test2函数运行完时局部变量c被销毁
  18. console.log(c); // ReferenceError
  19. }
  20. test1();

image.png
函数封装的是一个一个的功能,功能是输入x,输出y,输入就是参数,输出就是return
函数最好都有参数与返回值

四、作业

4.1 定义一个函数,从wp接收一个饮料的名称,函数返回对应的价格

  1. function test1(name) {
  2. switch (name) {
  3. case '可乐':
  4. console.log('3¥');
  5. break;
  6. case '矿泉水':
  7. console.log('1¥');
  8. break;
  9. case '脉动':
  10. console.log('5¥');
  11. break;
  12. case '营养快线':
  13. console.log('4¥');
  14. break;
  15. default:
  16. console.log('无');
  17. }
  18. }
  19. var name = window.prompt('请输入饮料的名称');
  20. test1(name);

4.2 定义一个函数,从wp接收第一个数,接收一个运算符号(+ - * / %),接收第二个数,利用这个函数做运算,并返回运算结果

  1. function test2(value1, type, value2) {
  2. switch (type) {
  3. case '+':
  4. console.log(value1 + value2);
  5. break;
  6. case '-':
  7. console.log(value1 - value2);
  8. break;
  9. case '*':
  10. console.log(value1 * value2);
  11. break;
  12. case '/':
  13. console.log(value1 / value2);
  14. break;
  15. case '%':
  16. console.log(a % b);
  17. break;
  18. default:
  19. console.log('输入格式错误');
  20. }
  21. }
  22. var value1 = Number(window.prompt('请输入第一个数字'));
  23. var type = window.prompt('请输入运算符');
  24. var value2 = Number(window.prompt('请输入第二个数字'));
  25. test2(value1, type, value2);

4.3 定义一个函数,从wp接收一个n,算出n的阶乘,不能用for循环

  1. function test3(n) {
  2. if (n < 0) {
  3. return '请输入一个正整数';
  4. }
  5. if (n === 0) {
  6. return 1;
  7. } else if (n > 0){
  8. return test3(n - 1) * n;
  9. }
  10. }
  11. var n = parseInt(window.prompt('请输入一个正整数'));
  12. console.log(test3(n));

4.4 定义一个函数,从wp接收一个n,算出斐波那契数列的第n项,不能用for循环

  1. function test4(n) {
  2. if (n <= 0) {
  3. return 0;
  4. }
  5. if (n === 1 || n === 2) {
  6. return 1;
  7. } else {
  8. return test3(n - 1) + test3(n - 2);
  9. }
  10. }
  11. var n = parseInt(window.prompt('请输入一个正整数'));
  12. console.log(test4(n));