一.初步了解函数
1.函数的定义和调用
1.1 函数定义
函数其实就是将多条语句组合成一个“语句军团”,集体作战
//定义一个函数,函数就是一组语句的集合
function fun(){
console.log(1);
console.log(2);
console.log(3);
console.log(4);
}
//函数调用
fun();
定义一个函数,用关键字function来定义
function后面有一个空格,后面就是函数名字,函数的 名字也是标识符,既然是标识符,那么命名规范和变量命名就是一样的。
定义一个函数也叫声明一个函数
function 函数名(){
}
函数如果不调用,那么里面的语句就不会执行,不调用就等于白写。
1.2 函数调用
调用一i个函数的方法非常简单,函数名后面加一个(),
( ) 是运算符, 表示执行一个函数
执行函数:
函数名()
一旦调用了函数,函数内部的语句就会执行
2.函数的参数
2.1 参数的了解
可以通过参数让函数内部的语句有所不同
定义函数的时候,内部语句可能有一些悬而未决的量,就是变量,这些变量,我们要求在定义的时候罗列在小括号中:
比如:
function fun(num){
console.log("这已经是我第” + num + "此说我爱你!");
}
调用的时候,要把这个变量的真实的值,一起写在括号里,这样随着函数的调用,这个值也传给了num';这就是参数传递
执行这个函数:
fun(99);
罗列在function小括号中的参数,叫做;
调用时传递的值,叫做
形式参数就像占位置,先把位置站好,等你来赋值
2.2 参数个数
参数可以有无数个,用逗号隔开。
//有多少形式参数都可以,都罗列出来
function fun( a, b ){
console.log( a + b);
}
fun( 2,6); //输出8
fun( 6,18); //输出24
定义函数的时候,不需要指定类型:
function sum( a,b){
console.log( a + b);
也就是说调用的时候,传进去的值是什么类型,就是形参a、b就是什么类型
sum( "5" , 20);
输出520 ,做的时连字符的运算
2.3 实参和形参个数不等
声明函数的时候和调用函数的时候参数个数可以不一样,也不报错。
- 实参个数小于形参个数
sum( 20 ); // NaN
以为只传了一个参数,b就没有传递,b被隐式的var了,所以值时undefined。
10+undefined就是NaN
也就是说没有实参传递二点形参就是undefined。
- 实参个数大于形参个数
sum( 10,20,30,40,50); //30
只有前两个参数被形参接受了,后面的参数无视了,
形参会按顺序接收实参,
2.4 arguments
每一个函数里面都有一个隐式的arguments,这个时系统已经给你创建好的,每个函数内部都有,arguments是类似于数组的类数组,就是实参列表
类数组本质上是一个对象,涵盖了所有的实参
调用函数的时候,比如:
fun(45,56,346,335,231);
此时函数内部,arguments就有一个下标,就依此等于上面调用的数:
arguments[0] //45
arguments[1] //56
arguments[2] //346
arguments[3] //335
arguments[4] //231
.....
如果函数里面有形式参数列表,那么是和arguments同步的:
function fun(a,b){
arguments[0] = 8;//改变第一个参数值
alert(a); // 8 ,弹出改变后的值
console.log( arguments.length); //实参的长度
console.log( fun.length); //形参的 长度
fun(45,56,346,335,231);
arguments的功能是模拟函数的重载,使得同一个函数,根据参数个数额不同,有不同的作用
4. 返回值
函数可以通过参数来接收东西,可以通过return的语句来返回值
function sum(a,b){
return a + b;//现在这个函数的返回值就是a+b的和
}
console.log( sum(5,4));//sum没有输出功能,就要用console.log输出
//sum(5,4)实际上就成为了一个表达式,用来计算结果
//计算结果就是9,相当于console.log(9);
函数只能有唯一的return,有if语句除外,因为if语句是分支语句
程序遇到了return,将立即返回结果,返回调用的地方,而函数内return后面的语句将不再执行
function fun(){
console.log(1);
console.log(2);
return; //返回一个空值
console.log(3);//这行语句不执行,因为函数已经return了所以不会打印3
}
fun(); // 1 ,2
程序是先执行内层在执行外层。
函数可以接收很多值,返回一个值
函数的意义:
- 在出现大量程序相同的时候,可以封装为一个function,这样只要写一次代码就可以调用很多次,减少代码耦合
- 在调用一个函数的时候,不用关心函数内部的实现细节,只要可以运用,并能给我们开发带来好处
- 模块化编程,然复杂的逻辑变得简单
4. 递归
函数内部又调用了函数自身,我们把这种情况叫做递归
斐波那契数列就是经典的递归算法:
1、1、2、3、5、8、13、21、34、55、89、144、233……
输出斐波那契数列
//1、1、2、3、5、8、13、21、34、55、89、144、233……
//fib(n) 就能得到第n位的数字
//fib(2) = 1
//fib(5) = 5
//fib(6) = 8
//fib(10) = 55
function fib(n){
if( n == 1 || n == 2){
return 1;
}else{
return fib( n - 1) + fib( n - 2);
}
}
//一点一点计算
for( var i =1; <= 55 ; i++){
console.log(fib(i));
}
二.函数表达式
定义函数处理使用function之外,还有一种方法,就是函数表达式。就是函数没有名字,称为“匿名函数”,为了能够调用它,我们把这个匿名函数,直接赋值给一个变量
var sum = function(a,b){
return a + b;
}
想调用这个函数的时候,就可以直接使用sum变量来调用。
console.log( sum(3,6) );
如果现在这个表达式中的function不是匿名函数,而是有名字的:
var sum =function fun(a,b){
return a + b;
}
那么JS表现非常的奇怪,在外部只能用sum()
来调用,fun()
会引发错误!
也就是说,JS这个奇怪的特性,给我们提了个醒,定义函数,只能用这两种方法中的其一,不建议杂糅:
第一种,通过函数声明定义函数
function sum(){
}
第二种,通过匿名函数的赋值定义函数
var sum = function(){
}
建议不要混用,这么写也不会错
var xixi = function haha(){
}
三.函数声明的提升
JS在执行前,会有一个解析的过程,会把所有的函数声明,都提升到了最最开头,然后再执行第一行语句
所以,function定义在哪里,都不重要,程序总能找到这个函数
//先调用
fun();
//然后定义
function fun(){
console.log("我是函数,我执行了");
}
不会引发错误,打印能正常执行。
3.1. 声明函数和函数表达式提升方式不同
函数声明会被提升,但函数表达式却不会提升
函数表达式提升的是变量,变量提升后并不是一个函数,所以在表达式之前执行,会报错,为类型错误,因为不是函数
fun() ;//报错
var fun = function(){
alert("我是函数,我执行了");
}
这提了个醒,没有极特殊的理由,都要使用function 关键字来定义函数,而不要使用函数表达式来定义函数.
3.1.1 函数优先
sum();//现在这个sum到底是函数还是变量8呢
//函数优先,遇到同名标识符,预解析阶段一定把这个标识符给函数
var sum = 8;//定义一个变量,是8
function sum(){
alert("我是sum函数,我执行了");
}
面试很容易靠,就常见的面试题:
foo();
var foo;
function foo(){
console.log(1);
}
foo = function(){
console.log(2)
}
函数优先,
现在foo
这个标识符冲突了,一个函数叫做foo
,一个变量也叫做foo
,预解析阶段,如果遇见标识符冲突,这个标识符给函数
四.IIFE
IIFE就是immediately-invoked function expression,即时调用函数表达式
如果一个函数,在定义的时候我们就直接想调用它,就是一个IIFE
视图在定义函数的后面,直接写圆括号:
function fun(){
alert("hello ");
}();
控制台报错,这是因为函数是一个函数体,并不是表达式,只有表达式能够用()来执行。
所以就要把function fun(){}“降级”,从函数体降级为表达式。
+function fun(){
alert("hello");
}();
-function fun(){
alert("hello");
}();
更通常更常用的:
(function fun(){
alert("hello");
})();
用这种方法定义的函数,名字是无效的,其他的地方是调用这个函数:
fun();
所以IIFE里面的函数,都是匿名函数:
(function(){
alert("哈哈");
})();
上面就是一个标准的IIFE.