javascript函数(声明,传参,返回值,递归)
1、函数的基本概念
- 函数:是由事件驱动的或者当他被调用时可执行的可重复使用的代码块。
- 空调是由遥控器控制或者当开关打开时,可运行的家用电器(工具)
特点:
- 封装代码----使代码更简洁
- 重复使用—在重复功能的时候直接调用就好
- 执行时机—随时可以在我们想要执行的时候执行
2、函数的创建和执行
1. 函数的创建
1、声明式
-
函数声明的关键字 : function
-
function 关键字 和 var 关键字的行为几乎一致,都会在内存上开辟一块空间,用来存储变量之中的数据;
function 函数名( 条件 ){
代码
}
-
规定 : 必须执行,不执行就报错;
-
规范 : 最好执行,不执行也不会报错,但是会让程序有一些负面影响。
-
函数定义的规范: 函数名的首字母小写!
- 函数的命名规则和变量命名规则完全一致;
- 函数推荐驼峰命名;
- 变量推荐_命名;
function foo(){
console.log("hello world");
}
- 函数定义了,会吧代码 默默的放在哪里不会去执行代码;
- 只要在程序主动调用的时候,代码才会执行!;
- 声明式-规定 : 不要漏掉函数的名字!;
2、赋值式
- 函数也是数据类型的一种;
- 基本类型 : 五种;
- 引用类型 : 三种 => function(){}(其中一种)
- 我们可以认为函数是一种数据;
- 赋值式函数声明可以没有函数名!;
- 其实就是和我们使用 var 关键字是一个道理了
- 首先使用 var 定义一个变量,把一个函数当作值直接赋值给这个变量就可以了
var foo = function(){
console.log("hello world");
}
- 函数定义和调用规范 : 先声明再调用!;
var foo = function poo(){
console.log("hello world");
// 只有在这个函数里面才会使用;
}
// poo 是无法被调用 , 因为他的作用范围是局部的;
2. 函数的执行
- 直接执行
- 通过行为执行
函数调用的两种形式:
- 你在代码之中调用;
- 直接写 函数名() 就可以了
function foo(){
console.log("hello world");
}
foo();
注意:
定义完一个函数以后,如果没有函数调用,那么写在 {} 里面的代码没有意义,只有 调用以后才会执行
2. 浏览器在特定时机帮你调用函数!;
- 事件行为;
- html标签进行触发 => 浏览器接受 => 浏览器调用函数;
<button id="btn">你点我一下试试</button>
function foo(){
console.log("hello world");
}
btn.onclick = foo
// console.log(btn);
// 在点击的时候会让浏览器调用对应的函数;
// btn 就是元素的id;
// onclick 是事件行为;
3、函数的参数(重点)
- 我们在定义函数和调用函数的时候都出现过 ()
- 现在我们就来说一下这个 () 的作用
- 就是用来放参数的位置
- 参数分为两种 行参 和 实参
// 声明式
function fn(行参) {
// 一段代码
}
fn(实参)
// 赋值式函数
var fn = function (行参) {
// 一段代码
}
fn(实参)
接收:形参
- 就是在函数内部可以使用的变量,在函数外部不能使用
- 每写一个单词,就相当于在函数内部定义了一个可以使用的变量(遵循变量名的命名规则和 命名规范)
- 多个单词(形参)之间以 , 分隔
// 书写一个参数
// 声明式
function fn(num) {
// 在函数内部就可以使用 num 这个变量
}
// 赋值式
var fn1 = function (num) {
// 在函数内部就可以使用 num 这个变量
}
// 书写两个参数
// 声明式
function fun(num1, num2) {
// 在函数内部就可以使用 num1 和 num2这两个变量
}
// 赋值式
var fun1 = function (num1, num2) {
// 在函数内部就可以使用 num1 和 num2 这两个变量
}
- 如果只有行参的话,那么在函数内部使用的值个变量是没有值的,也就是 undefined
- 行参的值是在函数调用的时候由实参决定的
发送:实参
- 在函数调用的时候给行参赋值的
- 也就是说,在调用的时候是给一个实际的内容的
function fn(num) {
// 函数内部可以使用 num
}
fn(100)
// 这个函数的本次调用,书写的实参是 100
// 那么本次调用的时候函数内部的 num 就是 100
fn(200)
// 这个函数的本次调用,书写的实参是 200
// 那么本次调用的时候函数内部的 num 就是 200
- 函数内部的行参的值,由函数调用的时候传递的实参决定
- 多个参数的时候,是按照顺序一一对应的
function fn(num1, num2) {
// 函数内部可以使用 num1 和 num2
}
fn(100, 200)
// 函数本次调用的时候,书写的参数是 100 和 200
// 那么本次调用的时候,函数内部的 num1 就是 100,num2 就是 200
多个参数的关系
- 原则上来说,形参和实参的数量应该一一对应
但,如果,二者数量不一致:-
形参多,实参少:多出来的形参为undefined
-
实参多,形参少:多出来的实参找arguments
-
arguments是一个在函数内部才能使用的,用来保存当前函数所有实参的类数组,也叫对象
-
可以通过索引和长度来解析arguments
-
- 形参比实参多 :
// 参数多了怎么办 ?
// 形参 : 变量 => 函数体之中;
// 实参数量比形参数量少; 其余未赋值的形参值都为 undefined;
function foo( a , b , c , d ){
console.log( a , b , c , d );
}
foo( 1 );
- 实参比形参多 :
- 剩下的实参都哪里去了 ?
- 剩下的参数都使用arguments关键字进行接收, 使用 [] 进行取出;
function foo( a ){
// console.log(a);
// 函数之中有一个关键字 : arguments => 接受所有的实际参数;
// arguments 里面可以存很多很多的数据;
// console.log( arguments );
// 想要取出复杂结构之中的数据 : 取出运算符 => .
// arguments.0
// Uncaught SyntaxError: Unexpected number
// 语法报错 : 不允许使用数字;
// JS之中的取出运算符 => .纯英文
// => [] 里面可以放任何数据;
// document.write() === document["write"]()
console.log(arguments[2]);
}
foo( 1 , 2 , 3 , 4 , 5 , 6 , 7 );
4、函数的返回值-return(重点)
- 将函数执行处理的数据,返回出来,
- 便于其他程序或用户调用或做二次使用
- 关键字 : return => 函数体内使用;
function foo(){
return "hello world";
}
console.log(foo());
// = > "hello world"
- return的特性
- 在函数之中,只要遇到了return关键字,表示函数执行结束,会立即跳出函数执行。
- 无论有多少个return ,只会执行第一个return,因为后面的就不执行了。
- 因此函数有一个特点, 返回值只能有一个;
function foo(){
return "hello world1";
return "hello world2";
return "hello world3";
}
console.log(foo());
// = > "hello world1"
- 函数的运算结果可以是什么样的数据类型;
- return 可以返回什么数据类型那 ?
- 任意数据类型都可以返回;
**如果函数返回了一个函数会发生什么 ? **
function foo(){
console.log("foo");
function poo(){
console.log("poo")
}
return poo;
}
var res = foo();
// 此时 res 里面存储的是 poo 函数的地址;
// 此时的 res 和 poo 完全一样;
res();
5、函数的递归(重点)
- 一个函数调用了他自身,这种现象叫递归
注意
-
递归就是函数自己调用自己
-
递归类似于循环
-
递归函数要注意停止返回,否则会造成死递归
-
递归比较消耗性能,尽量少用
我们想要把递归进行正经的应用:
- 终止条件 => 包裹在if之中的 return;
- 运算条件 => 算法; => 极简算法;
- 返回结果 => return ;
用递归做一个简单的案例:
// num 求 1 ~ num 的累加 ;
// 累加 : 1 + 2 + 3 + 4 + 5 + 6 ....
var count = 0;
function sum( num ){
// count(查看运行次数)
count ++;
// 这个运算的起始值,归到起始点;
// 终止条件(必须要有不然会照成死循环)
if( num === 1){
return 1;
}
// 运算条件
return sum( num - 1 ) + num;
}
// sum( 1 ); // 1;
// sum( 2 ); // sum(1) + 2; => 3;
// sum( 3 ); // sum(2) + 3; => 6;
var res = sum(100);
console.log( res );
console.log(count);