作业:日程安排

time 0m

函数基础

time 16m36s

函数定义

time 25m52s
image.png
数学中的函数与计算机中的函数有相同之处,也有不同之处
数学函数:输入x 得出y
任意x都有确定的y,x是自变量 y是f(x)函数
解析:在数学中f(x) x其实是指代的意思,f(1)用1替换掉所有x,x是指代、占位符,因为我不知道之后会传什么值,用它指代、占位置,先帮要传的值把位置占上了
学习编程与学习数学类似,公式数学高中公式并不多,数学是理科,不是文科,背诵的并不多

time 28m25s
计算机里面的函数就是函数式编程
函数式编程:用函数封装功能模块,代码复用,解耦合

  1. function test(a,b,c){
  2. //执行语句
  3. }

函数解决什么问题?让代码容易复用

time 30m45s
image.png
三种情况想完成一个功能,其实是一个功能
这就有耦合的情况,重复代码块太多了

高内聚 低耦合

time 31m
编程最基本的原则,高内聚低耦合,
高内聚,我们开发的模块,它们代码相关性强,紧密联系比较强
time 32m24s
低耦合:希望把重复的代码,抽象提取出来,组成一个独立的功能体

模块的单一责任制

time 34m22s
一个模块干一件事情

高内聚低耦合,让代码块重复更少
解耦合,在js中,解耦合最常用的方式是函数,函数一般比较常用

time 35m38s
当代码中重复代码多的时候用函数封装重复的部分
如下代码,因为for函数重复次数多,所以用函数封装for函数,重复多的部分
这样如果改成都是0-5就不用改变3处,而只是改变一处就行了
image.png

最基本的函数写法 - 函数声明

time 36m23s
用function关键字,var也是关键字

  1. function test(){}
  2. var test=1;
  3. /*function test与var test类似*/
  1. function test (参数){
  2. 函数执行语句
  3. }

函数作用

time 38m28s
function就相当于一个电脑,这个电脑是在使用之前已经把软件安装好了,用的时候开机用,不用的时候关闭就行了
比如用函数时test();
函数里面的内容就像电脑里面的软件,安装软件就像代码里面实现的功能,比如电脑里面希望有个英雄联盟,那肯定安装英雄联盟的软件,就有了英雄联盟的功能,类似于在函数中写英雄联盟的功能

函数的功能就像电脑里面的软件,安装软件的过程就是在函数中写代码的过程,

函数执行

time 41m29s

  1. test();
  2. test();
  3. test();
  4. function test(){
  5. console.log('我是很牛的函数');
  6. }
  7. /*
  8. * 我是很牛的函数
  9. 我是很牛的函数
  10. 我是很牛的函数
  11. */

只要test()调用函数,函数才会执行,不调用不会执行的

函数命名

time 43m
函数名的命名规则
不能数字开头
字母 数字 下划线 $ 组成
小驼峰命名法 myFunction 复合单词
my_wonderful_test这样也可以,不会报错,但ecma建议、推荐用小驼峰命名法

定义函数的方法

time 45m56s
函数声明的方式去定义,函数内部声明的值,在函数外部不能访问

  1. function test(){
  2. var a=b=1;
  3. console.log(a,b);
  4. }
  5. test();//1 1
  6. console.log(a,b);
  7. /*ReferenceError: a is not defined*/

time 49m23s
表达式,字面量

  1. /**
  2. *表达式 ,也叫字面量
  3. */
  4. var test=function test(){
  5. var a=1,
  6. b=2;
  7. console.log(a,b);//1 2
  8. }
  9. test();
  1. var test=function test1(){
  2. var a=1,
  3. b=2;
  4. console.log(a,b);//1 2
  5. }
  6. test1();
  7. /*ReferenceError: test1 is not defined
  8. * 报错test1没有被定义*/
  9. /**
  10. * 过程是怎么样的?
  11. * 我声明了一个test变量,之后把function test1这个函数赋值给了test这个变量
  12. */

time 50m38s

  1. /*这两个是一样的*/
  2. // var test=function (){
  3. var test=function test1(){
  4. var a=1,
  5. b=2;
  6. console.log(a,b);//1 2
  7. }
  8. // test1();
  9. console.log(test.name);//test1
  10. /*因为test赋予test1函数时,就赋予了它功能,test是函数,可以打印1,2的值,这是test的功能
  11. * 当写上test1时是可以忽略的*/

time 51m54s

  1. var test=function test1(){
  2. var a=1,
  3. b=2;
  4. console.log(a,b);//1 2
  5. test1()
  6. // test()
  7. /*都是一样的结果,递归,无限循环了*/
  8. }
  9. console.log(test.name);//test1
  10. test();

函数内部可以调用test1,有它没它是有区别的
image.png

time 55m01s

  1. /**
  2. *匿名函数表达式 ,也叫函数字面量
  3. */
  4. var test = function () {//->匿名函数,因为function没有名字
  5. var a = 1,
  6. b = 2;
  7. console.log(a, b);//1 2
  8. }
  9. console.log(test.name);//test
  10. test();

字面量

time 55m42s

  1. var a = 10;/*10就是字面量*/
  2. var a = "我爱编程";/*也是字面量*/
  3. var a = [];/*数组也是字面量*/
  4. var a = {};/*对象也是字面量*/
  5. var a =function () {
  6. } ;
  7. /*函数也是字面量,把一个函数赋值给test、a就是变量,赋值给一个变量
  8. * 赋值的过程,函数就是字面量了*/

函数的组成部分

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

  1. function test() {
  2. var a = 1,
  3. b = 2;
  4. console.log(a + b);
  5. }
  6. test();//3

这里面a,b是在函数里面声明的值,外界不能用a、b的值,不能改变a、b的值,test()运行永远打印3,打印不了别的
现在,我想让函数可以打印别的值,可以修改a、b的值,这样只能在参数里面写a、b

  1. function test(a, b) {
  2. /* var a = 1,
  3. b = 2;*/
  4. console.log(a + b);
  5. }
  6. test(1, 2);//3

image.png

time 1h2m7s

  1. var aa = Number(window.prompt('a'));
  2. var bb = Number(window.prompt('b'));
  3. function test(a, b) {
  4. // var a, b;//就相当于在外界声明一个a,b
  5. console.log(a + b);
  6. }
  7. test(aa, bb);
  1. function test(a, b) {
  2. var a, b;//就相当于在外界声明一个a,b
  3. console.log(a + b);
  4. }
  5. test(1,2);//3

形参实参的区别、关系

time 1h3m25s

  1. /*占位->形式上占位,形式参数 形参*/
  2. function test(a, b) {
  3. var a, b;//就相当于在外界声明一个a,b
  4. console.log(a + b);
  5. }
  6. /*调用函数,函数运行,传入实参,1、2是实参*/
  7. test(1,2);//3

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

参数顺序

time 1h5m22s
函数顺序不能颠倒

总结

time 1h5m56s
参数有点像函数内部声明的变量,类似于函数内部声明的变量
不同之处是参数可以在函数调用时赋值,函数内部声明变量无法在函数调用时赋值,改变

  1. function test() {
  2. var a, b;
  3. console.log(a + b);
  4. }
  5. /*调用函数,函数运行,传入实参,1、2是实参*/
  6. test(1,2);//3

调用时改变不了a、b

  1. function test() {
  2. var a, b;
  3. /*想在函数调用时改变这里面的a、b,现在肯定改变不了*/
  4. console.log(a + b);
  5. }
  6. test(1,2);//NaN

如果想在函数调用是改变某个值,不想让函数中某个值是定值,不可以改变,就把它作为参数

  1. function test(a, b) {
  2. // var a, b;
  3. /*想在函数调用时改变这里面的a、b,现在肯定改变不了*/
  4. console.log(a + b);
  5. }
  6. test(1, 2);//3

函数参数传递时,参数的数据类型不会变

time 1h7m10s
没有数据类型的限制,什么数据类型都可以传进去

  1. function test(a, b) {
  2. console.log(a, b);
  3. }
  4. test(1, 2);//1 2
  5. test('false', NaN);//false NaN

形参与实参数量可不等

time 1h7m58s
形参与实参个数对不上不会报错
形参与实参数量可不等

  1. function test(a, b, c) {
  2. console.log(a, b, c);
  3. }
  4. test(1, 2);//1 2 undefined

arguments

time 1h11m56s
既然实参、形参个数可不等,那么函数能不能知道传递了那些实参?
用arguments可以知道

  1. function test(a, b) {
  2. console.log(a, b);
  3. console.log(arguments);
  4. }
  5. test(1, 2, 3);

image.png
image.png

arguments有length可以进行for循环

time 1h13m33s
arguments有length可以进行for循环

  1. function test(a, b) {
  2. for (var i = 0; i < arguments.length; i++) {
  3. console.log(arguments[i]);
  4. }
  5. }
  6. test(1, 2, 3);//1 2 3

形参的长度也可以知道,用函数.length

time 1h14m33s
形参的长度也可以知道,用函数.length

  1. function test(a, b) {
  2. console.log(test.length);//2
  3. console.log(arguments.length);//3
  4. }
  5. test(1, 2, 3);

根据输入实参,求累加和

time 1h15m50s
最大的问题,不知道实参的个数与值?利用arguments
image.png

  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);

可以在函数内部更改实参的值

time 1h21m49s
可以在函数内部更改实参的值
这样也符合常理,比如用户填了一个不合法的值,我可以改变这个值

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

只能修改传入值的实参的值

time 1h23m12s
实参没有传b,不能改变,因为调用函数时没有给b赋值,没有b的实参,是undefined,没有实参b,所以更改不了实参
实参b,形参b,形参b可以改变,打印为3

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

行实参有映射关系

time 1h26m43s
a与arguments[0]是不是一个变量产生的值,是不是一个东西

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

不是。因为a是原始值存在栈内存,而argument是引用值,存在对内参,arguments[0]是arguments对象上面的引用值,有新的地址,与a的地址不一样。

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

return

time 1h31m38s

没写return的情况,js引擎自动添加

  1. function test(){
  2. console.log('我正在执行');
  3. console.log('我正在执行了就结束这个函数');
  4. /*不是运行完最会一句console就完事了的*/
  5. }
  1. function test(){
  2. console.log('我正在执行');
  3. console.log('我正在执行了就结束这个函数');
  4. /*不是运行完最会一句console就完事了的*/
  5. return;
  6. /*js引擎自动默认加了一个return来结束函数,隐式添加一个return,偷偷摸摸添加*/
  7. }

return终止函数运行

time 1h33m37s
下面的console是不会执行的,return写在哪里下面函数是不会执行的

  1. function test(){
  2. console.log('我正在执行');
  3. return;
  4. console.log('我正在执行了就结束这个函数');
  5. }
  6. console.log(test());
  7. /*我正在执行
  8. undefined*/

应用

time 1h35m12s
image.png
判断空值,结束函数,有值打印

image.png
设置默认值,判断
return两种作用1返回相应的值 2终止函数运行

time 1h41m26s
会打印两个,因为console没有终止函数运行,函数继续运行
image.png
image.png

time 1h44m29s

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

全局变量与局部变量

time 1h53m14s

总结

time 2h5m25s
函数式编程是什么?
image.png

布置作业

time 2h11m34s

arguments


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

三、变量类型

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
函数最好都有参数与返回值

四、作业

time 2h11m34s

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));

扩展总结思考

这部分可以放到开头也可以放到结尾

问题

这节课讲了什么?
函数的声明、作用
形参实参
argument
return

函数的作用是什么?意义何在?