一、什么是函数
函数:一般是由事件驱动的,为了实现特定功能,可以重复调用的一段可以执行的代码块。
二、函数的分类
从定义角度分:内置函数、用户自定义函数
内置函数:字符串,数学函数,数组函数,js 系统给我们提供的函数
自定义函数:自己定义的函数:函数的声明
从参数的角度分:有参函数、无参函数
从返回值的角度分:有返回值函数、无返回值函数
(1)无参无返回值函数的定义与调用:
function 函数名称(){
函数体;
}
函数名()
(2) 有参无返回值函数:
function 函数名称(形参1,形参2,形参3...){
函数体;
}
函数名称(实参1,实参2,实参3...)
1、形参:定义函数时所用的参数称为形参
形参的本质是用来接收函数调用时传递过来的数据的存储空间;
形参只有在函数调用时才开辟空间,当函数执行完毕后,该空间被释放。
形参只能在函数内部使用,因为它属于局部变量
2、实参:调用函数时使用的参数称为实参
实参的本质是函数要处理的具体的数据
一个函数可以有多个实参,用逗号分隔,形成“实参列表”
实参可以是字面量、变量、表达式
3、实参和形参的关系
1)函数被调用时,实参会被传递给形参,但是形参不能传递给实参,即传递是单项的;
2)默认情况下实参和形参在数据传递时是平行传递的,即第一个实参传递给第一个形参,第二个实参传递给第二个形参,以此类推;
3)js 中形参的个数和形参的个数可以是不一致的,如果实参 小于 形参,那么没有介绍的数据的形参的值为 undefined;
(3) 有参返回值函数的定义格式
function 函数名称(形参1,形参2...){
函数体;
return 返回值
}
var 变量 = 函数名称(实参1,实参2...)
三、值传递和地址传递
值传递:指将具体数据(基本类型的数据)的副本传递给对方,对方在操作这个数据时不影响原始数据
var arr = [10,20,30,40,50];
function fn(val){
val = 100;
}
fn(arr[0]); //调用函数 fn 时传递的时 arr[0]中数据的副本-----值传递
console.log(fn(arr[0]));//原数组不受影响
地址传递:指将引用类型的数据在对内存中的地址传递给对方,对方在操作时,其实操作的就是原始数据,即原有数据被影响
var arr = [10,20,30,40,50];
function fn(val){// val 指向了数组
val[0] = 100;
}
fn(arr); //数组名称中保存的是数组在堆内存中的地址--------地址传递
console.log(arr);//原数组中的值变了
四、return 返回值
1、返回值:指函数被调用后,向调用者返回的一个数据,函数内部利用 return 关键字将返回值返回
2、return 关键字的使用格式: return 返回值;
3、return 使用时的注意事项:
1)返回值可以是变量,字面量,表达式
2)函数内部可以有多个 return, 但是只能执行一个,return 关键字除了返回数据,还具有结束函数执行的功能
3)如果函数中没有设置 return ,那么在调用函数时,其实后台会向调用者返回一个值 ---- undefined
4)在定义函数时,return 和它后面的返回值不要换行,因为换行后,后台会认为 return 后面没有返回值。
5)如果要将 return 用左结束函数的功能,那么可以采用 return 的格式;
五、定义函数的方式
1、函数声明的方式
function 函数名称(){
函数体;
}
函数名称();
2、函数表达式
var 变量名称 = function(){
函数体;
};
var fn = function(){
for (var i = 1; i <= 10; i ++){
if ( i % 2 == 0 ){
console.log(i)
}
}
};
fn();
1)函数表达式方式创建的函数是没有名称的函数
2)变量中存储的是对函数的引用
3)函数声明方式和函数表达式方式的区别,函数声明方式定义的函数可以在定义之前调用该函数,但是函数表达式方式定义的函数,不可以在定义之前调用。因为函数声明方式定义的函数有函数声明提升操作,而函数表达式方式定义的操作没有函数声明提升操作,只有变量声明提升操作
3、利用 function 构造方法创建函数
var 变量名称 = new function('参数1','参数2'...);
调用方式:
变量名称(实参1 , 实参2, 实参3...);
构造方法 function 中的参数可以有多个,那么前面的参数表示函数的形参,最后一个参数表示函数体。
注意: 这种方式定义的函数也不可以在定义之前调用,因为它也只有变量声明提升操作
var add = new function('num1','num2','num3','var sum = num1+ num2 + num3; console.log(sum);');
add(1,2,3);
六、 变量的分类:全局变量、局部变量
全局变量:定义在函数外部的变量被称为全局变量;
局部变量:定义在函数内部的变量被称为局部变量。
区别: 1、全局变量可以在整个文档中使用
2、局部变量只能在定义它的函数内部使用
3、函数内部的形参也是局部变量,也只能在函数内部使用
4、如果全局变量和局部变量同名,那么全局变量会被屏蔽
5、如果局部变量和全局变量同名,那么要使用全局变量,可以在变量名称前面加 window. 或者 this. ,因为全局变量是给 window 对象绑定的属性
七、 arguments 对象
1、arguments:该对象是函数内部的一个对象,即该对象只能在函数内部使用,不可以在外面使用。它的作用是用来管理函数被调用时传递过来的实参(数据),它不是一个数组,它是一个伪数组,在管理实参时也是用下标的方式对实参进行了编号,即可以使用 arguments[下标]的形式操作实参。
2、形参 和 arguments 的关系: 形参和 arguments 都可以管理实参,而且他们管理的是同一份数据。在操作实参时,可以使用形参,也可以用 arguments , 为了方便通常使用形参。
在定义函数时,到底需不需要定义形参?
--- 如果实参的个数是确定的,那么我们就定义形参,如果实参的个数是不确定的时候就不定义形参,用 arguments 操作
3、arguments 对象包含两个属性: length、callee
1)length 属性: 获取实参个数;
2)callee 属性: 该属性的作用是用来获取 arguments 对象所在的函数,即callee 属性指向了 arguments 对象所在的函数,常与递归函数结合使用,或与匿名自执行函数结合使用。
--- 如果要判断一个元素是否为数组, 那么可以使用 Array.siArray 方法
1、 格式: Array.isArray(数据);
2、返回值: true(是数组) 、 false(不是数组)
var arr = [1,2,3];
var res = Array.isArray(res);
console.log(res);
八、JavaScript 中没有重载函数
重载函数:所谓重载函数就是指,两个函数的名称相同,但是他们形参的个数不同,或者形参的类型不同,那么我们把这两个函数互称为重载函数
function fn(a,b){
}
function fn(a,b,c){
}
//这两个互称为重载函数
// 注意: JavaScript 中没有重载函数,在JavaScript 中,如果函数名称相同,那么后面的函数会覆盖前面的函数
利用 arguments 对象模拟重载函数
function fn(){
if(arguments.length == 1){
console.log('只有一个形参' +i);
} else if(arguments.length == 2){
console.log('有两个形参' + i)
}
}
fn();
九、递归函数:
递归函数:所谓递归函数就是指在一个函数内部调用了自己的函数被称为递归函数。
function fn(){
fn();
}
fn();
注意:在使用递归函数时,一定要确定递归函数的“出口”,即在某个时刻能够让函数不再调用自己,如果递归函数没有出口,那么会出问题。
function fn(n){
if(n == 1){
return 1;
}
return arguments.callee(n - 1) +n;//推荐递归函数内部使用 arguments.callee 属性来引用当前函数
}
十 、匿名函数
概念: 没有函数名称的函数;匿名函数可以和事件相结合,常用格式如下:
html 元素 . on事件名称 = function(){
};
十一 、 回调函数
概念: 如果一个函数被当作另外一个函数的参数,那么这个被作为参数的函数就是回调函数,回调函数常用匿名函数;
var arr = [1,2,3,4,5];
var res = sort(function(a,b){
return a -b;
})
console.log(res);
十二、 匿名自执行函数
概念: 没有名称,且不需要手动调用的函数,
格式:
1、无参五返回值的匿名自执行函数
(function(){
函数体;
})();
2、有参无返回值的匿名自执行函数
(function(形参1、形参2、形参3...){
函数体
})(实参1、实参2、实参3...)
3、有参有返回值的自执行函数
var 变量名称 = (function(形参1、形参2...){
函数体;
return 返回值;
})(实参1、实参2...)
注意:匿名自执行函数,通常用来创建块级作用域。