函数
函数声明
函数就是功能(function)
我们可以自己封装一些语句在函数内部,函数就具有了某一种特定的功能。
声明函数:
function 空格隔开函数名后面紧跟小括号,小括号中可以书写参数,将功能语句书写在大括号中表示整体。
函数声明只是告诉我们函数有什么功能有语句,并不会执行。
// 声明函数
function fun() {
// 将功能语句书写在大括号中,表示一个整体
console.log(1);
console.log(2);
console.log(3);
}
函数调用
函数的声明不会执行,必须调用函数。
调用函数:函数名();
函数是一个整体,调用整个大括号都会执行。
// 声明函数
function fun() {
// 将功能语句书写在大括号中,表示一个整体
console.log(1);
console.log(2);
console.log(3);
}
// 调用函数
// 函数名()
fun();
结果:
函数声明一次,可以多次调用,函数的执行位置只有调用位置有关和声明位置没有关系。
fun();
console.log(4);
fun();
console.log(5);
// 函数声明一次可以多次调用,执行位置和声明没有关系,和调用有关
结果:
函数优点:函数声明一次可以多次调用,简化代码书写。
参数
函数可以帮我们封装一些代码,代码可以重复调用,函数留了一个接口,就是我们的参数,可以通过参数的变化让我们的函数发生不同作用。
参数就是变量,命名规则和变量名一样,参数不用声明var
形式参数:函数在声明时,小括号中书写的是形式参数。(行参)
实际参数: 函数在执行时,小括号中书写的是实际参数(实参)
传参:函数调用时,将实际参数赋值给形式参数这个过程,就是传递
js是动态语句,参数的数据类型也是动态变化,取决于实际参数类型。
function sum(a, b) {
// 功能
console.log(a + b);
console.log(typeof a);
console.log(typeof b);
}
实际参数,和形式参数个数问题。
函数内部有一个类数组对象,arguments保存的是实际参数
1实际参数个数<形式参数个数。优先将实参赋值给前面的形参,没有赋值结果undefined.
function fun(a,b) {
// a,b形参
// arguments保存实际参数
console.log(arguments);
console.log(a);
console.log(b);
}
// 调用实参少,优先将值赋值给前面的参数,么有赋值undefined
fun(10);
结果:
2 实际参数>形式参数,将多余实际参数直接舍弃
函数的优点2
:函数有参数,相当于给我们提供一个API接口,我们可以通过接口去调用函数,执行不同的操作,后面封装函数的时候,只需要了解API的用途就够了,就是传参之后有什么结果,不用去了解函数里面的构造。不论是自己的函数还是用的别人封装好的函数,都只需要知道怎么用就够了。
return
返回值:return可以接收参数,作为函数的返回值。返回值不会输出,想看输出结果console.log()
// 声明函数
function sum(a,b) {
return a + b;
}
// 调用
console.log(sum(2,5));
返回值相当于将我们的函数变成了一个表达式。利用这个特性,我们可以将函数作为一个实际参数,传递给另外一个函数。
sum(10,sum(15,5))
return特性:函数内部遇见return会立即返回,后面的语句不会再执行。
// return特性: 函数内部遇见return会立即返回
function fun() {
console.log(1);
return;
console.log(2);
console.log(3);
}
fun();
结果:
函数的优点3
:我们可以将一个函数作为返回值,传递给另外一个函数。有利于我们的模块化编程。
模块化编程
人类从古至今,习惯将事情分工,将一些内容做成一些公共模块,模块可以重复反复使用。
模块化编程:将一些基础的公共的部分单独封装到一个函数内,可以多次被调用。
注意:模块化编程,可以让我们的程序更加优化,各个小模块要尽量功能单一,提高重复使用率。
函数
函数表达式
函数表达式也是函数声明的一种方法。
将一个匿名函数(拉姆达函数)赋值给一个变量。
函数表达式结束必须书写分号。
var fun = function() {
console.log(10);
};
调用:函数名();
fun();
函数的数据类型
简单数据类型:number,string,boolean, undefined
引用数据类型:object,function
function关键字,函数表达式数据类型都是function
console.log(typeof fun);
console.log(typeof fun2);
简单数据类型:变量可以接收任何赋值,可以将变量赋值给另外的一个变量,实质上是将变量保存的值复制一份,变量改变不会互相影响。
var a = 10;
var b;
// a是简单数据类型,将10复制一份然后赋值给b
b = a;
// 改变变量,其他的不受影响
a = 20;
// 变量可以多次赋值,保存最后一次
console.log(a);
// a改变不影响b
console.log(b);
引用数据类型:变量可以接收任何赋值,可以将变量赋值给另外的一个变量,如果变量保存的是引用数据类型,是将变量的指针复制(地址)指向另一个变量,变量改变会互相影响。
// 引用数据类型
var fun;
function fun2() {
console.log(1);
}
// 将函数fun2赋值给fun,实质是将fun2的指针指向了fun
fun = fun2;
// 函数可以打点调用属性,使用=进行赋值
fun2.haha = "哈哈";
fun.xixi = "嘻嘻";
console.log(fun2.haha);
// 验证fun可不可以调用haha
console.log(fun.haha);
// 验证fun2可不可以调用xixi
console.log(fun2.xixi);
总结:简单数据类型赋值的是值,引用数据类型赋值的是地址。
函数声明的提升
变量可以先使用再声明,不会报错,结果是undefined(变量声明只提升声明语句不提升赋值语句)
函数也可以先使用在声明,也可以进行声明提升。
如果使用function关键进行声明,可以将函数名提升到所有语句之前,又因为函数保存的是指针,可以通过指针找到函数定义,使用时不会报错,并且可以正常调用函数。(相当于将函数的整体进行提升
)
fun();
// 再声明
function fun() {
console.log(1);
}
使用函数表达式进行提升,只提升变量名,函数的定义不能进行提升,先调用函数会报错。
// 先调用
fun2();
// 再定义
var fun2 = function() {
console.log(2);
}
/*
提升变量声明
var fun2;
其他语句原位置执行
fun2();
fun2 = function() {console.log(2)};
*/
总结:在声明函数,一般我们都使用function关键字这种,不会出错误。
并且一般我们习惯先书写函数的调用,将声明书写在所有语句之后,便于代码读取。
变量名和函数名(function关键字)相同,优先提升函数名,也就是将名字优先给函数使用。
console.log(fun);
// 后声明
var fun = 10;
function fun() {
console.log(20);
}
函数表达式和function关键字同名,将名字优先给function关键字使用。
举例:
// 先调用
fun();
// 声明
var fun = function() {
console.log(1);
}
function fun() {
console.log(2);
}
/*
预解析:
funciton fun;fun名字已经声明
var fun不会再书写
其他语句原位置执行
fun();
fun = function() {}
*/
fun();