一、函数基础
利用函数来实现低耦合高内聚
// 函数基础function test(a, b, c){// 执行语句}// 一下代码耦合度比较高if(3 > 0){for(var i = 0; i < 10; i++){console.log(i);}}if(2 > 0){for(var i = 0; i < 10; i++){console.log(i);}}if(1 > 0){for(var i = 0; i < 10; i++){console.log(i);}}// 耦合// 低耦合,高内聚 -> 单一模块责任制// 可以利用函数来节耦合function test(){for(var i = 0; i < 10; i++){console.log(i);}}if(3 > 0){test();}if(2 > 0){test();}if(1 > 0){test();}
1.1、函数最基本的写法,函数声明
函数只有调用了,才会执行,函数可以执行多次
// 函数最基本的写法,函数声明function 函数名(参数「可选」){// 执行语句}// 函数只有调用了,才会被执行test();function test(){console.log('我要开始执行函数了哦');}test();
1.2、函数的命名规则
使用数字、字母、下划线、$组成,但是不能以数字开头
- 严格区分大小写
- 不能使用关键字和保留字
-
二、函数的种类
2.1、声明式函数
// 声明式函数function test(){var a = 1,b = 2;console.log(a ,b);}test();
2.2、表达式 函数字面量
// 匿名函数表达式 函数字面量var test = function func(){ //func这个函数名只能在函数内部使用,一般用于递归var a = 1,b = 2;console.log(a, b);}test();func(); //Uncaught ReferenceError: func is not defined
2.3、匿名函数表达式
// 匿名函数表达式 字面量var func = function(){console.log('我是匿名函数表达式');}func();
2.4、函数的组成
函数名
- 参数「可选」
- 必须要有return,如果不写,JS引擎在解析代码的时候会自动加上
```javascript
// 函数的组成:函数名、参数「可选」、return返回,不写JS引擎在解析代码的时候会自动加上
function 函数名(形参「可选」){
}// 执行语句return;
var aa = Number(window.prompt('a'));var bb = Number(window.prompt('b'));// 占位,形式上占位,形式参数, 形参function func(a, b){var sum = a + b;console.log(sum);return;}// 实际传递的参数,实参func(aa, bb);
<a name="X79Vf"></a># 三、函数形参和实参的映射关系<a name="DM4ED"></a>## 3.1、函数的形参数量和实参数量可以不相等- 函数的形参数量和实参数量可以不相等- 函数执行时,如果不传递实参;那么函数的形参默认值是undefined```javascript// 函数形参和实参的映射关系// 函数的形参数量和实参数量可以不相等// 函数的形参默认值是undefinedfunction func1(a, b, c){console.log(a, b, c);}func1(1, 2);function func2(a, b){console.log(a, b);}func2(1, 2, 3);
3.2、实参集合arguments
- 在实参里面传递了值,可以在函数内部修改这个值
- 在实参里没有传递这个值,在函数内部给这个形参赋值是没有用的
函数的形参和实参存在映射关系,但绝对不是同一个东西
// 函数的实参集合arguments// 在实参里面传递了值,可以在函数内部修改这个值// 在实参里没有传递这个值,在函数内部给这个形参赋值是没有用的// 函数的形参和实参存在映射关系,但绝对不是同一个东西function func1(a, b){console.log(arguments);}func1(1, 2, 3, 4, 5);
循环打印实参集合
// 循环打印实参集合function func2(){for(var i = 0; i < arguments.length; i++){console.log(arguments[i]);}}func2(1, 2, 3, 'a');
利用实参实现任意数求和
// 利用实参集合求任意数的和var a = Number(window.prompt('请输入a的值'));var b = Number(window.prompt('请输入b的值'));var c = Number(window.prompt('请输入c的值'));function sum(){var total = 0;for(var i = 0; i < arguments.length; i++){total += arguments[i];}console.log(total);}sum(a, b, c);
3.3、函数形参和实参的长度
// 函数形参和实参的长度function func(a, b){// 打印函数形参的长度console.log(func.length);// 打印函数实参的长度console.log(arguments.length);console.log(arguments[2]);}func(1, 2, 3, 4, 5);
3.4、关于函数内部是否可以修改实参值的情况
如果在函数执行时,传递 了实参,那么在函数内部是可以修改这个实参的
如果在函数执行时,没有传递实参,那么在函数内部是无法修改该值的
// 函数内部是否可以修改实参值的问题// 函数在执行时传递了实参,那么在函数内部可以修改该值function func1(a, b){a = 3;console.log(arguments[0]); // 3}func1(1, 2);// 函数执行时没有传递实参,那么在函数内部无法修改该值function func2(a, b){b = 4;console.log(arguments[1]); // undefined}func2(1);
四、函数中的return
每一个函数都有return,如果不写,那么JS引擎在解析代码的时候会在函数最末尾加上return
return有两个作用,一是终止函数的作用,return下面的代码将不会再执行;而是返回一个值,这个值可以是任意类型的,与此同时它仍旧具备终止函数运行的作用
// 函数中的return// 每一个函数都有return,如果不写,那么JS引擎在解析代码的时候会在函数最末尾加上return// return有两个作用,一是终止函数的作用,return下面的代码将不会再执行;而是返回一个值,这个值可以是任意类型的,与此同时它仍旧具备终止函数运行的作用function func(){console.log('我要开始执行函数了');return; // return下面的代码就不会被执行console.log('我已经执行完函数了');}
|| 遇到真就返回,遇到假就往后走,走到最后不管真或者是假都返回该值
&& 遇到假就返回,遇到真就往后走,走到最后不管真或者是假都返回该值function func1(name){if(!name){return;}console.log(name);}func1();func1('liangyu');// 代码优化// || 遇到真就返回,遇到假就往后走,走到最后不管真或者是假都返回该值// && 遇到假就返回,遇到真就往后走,走到最后不管真或者是假都返回该值function func2(name){return name || '您没有填写姓名';}console.log( func2());console.log(func2('mac'));
return返回值:可以返回任意类型的值,return后面的代码将不再执行,也有终止函数的作用
// 返回值returnfunction func1(name){if(!name){return '您没有填写姓名';}return name;}console.log(func1());console.log(func1('mac'));// 代码优化function func2(name){return name || '您没有填写姓名';}console.log(func2());console.log(func2('liangyu'));
五、初始函数作用域 [[scope]]
- 函数体内部可以访问外部的变量,外部打印执行是无法访问到函数内部的变量的
- 越里面的函数越能访问到外面的变量,越是外面的访问函数内部的变量是访问不到的
- 越里面的函数是可以修改外面的变量的
- 暂且理解:每一个函数都是一个独立的作用域
// 初始函数作用域 [[scope]]// 函数体内部可以访问外部的变量,外部打印执行是访问不到函数体内部的变量的a = 1;function func(){var b = 2;console.log(a);}func(); // 1console.log(typeof(b));console.log(b);
越里面的函数越能访问到外部的变量,越外面的访问函数内部的变量是访问不到的
// 越里面的函数越能访问到外部的变量,越外面的访问函数内部的变量是访问不到的// 全局变量a = 1;function test1(){// 局部变量var b = 2;console.log(a, b);function test2(){// 局部变量var c = 3;}test2();console.log(c);}test1();
越是里面的函数越能修改函数体外的变量
// 越是里面的函数越能修改函数体外的变量a = 1;function test1(){var b = 2;function test2(){var c = 3;a = 3;}test2();}test1();console.log(a);
暂且理解:每一个函数都是一个独立的作用域
// 暂且理解:每一个函数都是一个独立的作用域function test1(){var a = 1;console.log(b);}function test2(){var b = 2;console.log(a);}test1();test2();
六、函数式编程
函数式编程:一个固定的功能或者是程序段被封装的过程,实现一个固定的功能或者是程序;这个封装体需要一个入口和出口
- 入口就是形参
出口就是返回 return
// 函数式编程:一个固定的功能或者是程序段被封装的过程,实现一个固定的功能或者是程序;这个封装体需要一个入口和出口function func(str){return str;}console.log( func('liangyu'));
七、作业
- 定义一个函数,从window.prompt接收饮料名字,返回对应的价格
- 定义一个函数,从window.prompt接收第一个数,接收一个运算符「+ - * 、 %」,再接收一个数,利用这个函数做运算并返回结果
- 定义一个函数,从window.prompt接收一个n,算出n的阶乘;不能用for循环
- 定义一个函数,从window.prompt接收一个n,算出斐波拉契数列的第n为;不能用for循环
