一、函数的概念

  • 对于js 来说,函数就是把任意一段代码放在一个盒子里面。
  • 在我想要让这段代码执行的时候,直接执行这个盒子里面的代码就行
  • 函数就是对一段代码的封装,在我们想调用的时候调用
  • 函数的几个优点
  1. 封装代码,使代码更加简洁
  2. 复用,在重复功能的时候直接调用就好
  3. 代码执行时机,随时可以在我们想要执行的时候执行
//正常书写代码方式
for(var i = 0; i < 10; i++){
	console.log(i);
}

//用函数封装代码,这个{}就相当于所说的盒子
function fn(){
	for(var i = 0; i < 10; i++){
		console.log(i);
	}
}

二、函数定义和调用

  • 函数的定义:相当于把代码放在盒子里
  • 函数的调用:相当于执行盒子里的代码

1.函数的定义

  • 定义阶段就是我们把代码放在盒子里面
  • 我们就要学习怎么放进去,也就是书写一个函数
  • 我们有两种定义方式声明式赋值式
1.1、声明式函数
  • 使用function这个关键字来声明一个函数
  • 语法:function 函数名() {};
  • 参数:
    • function:声明函数的关键字
    • 空格:分隔关键字和函数名
    • 函数名:这个函数的名字
    • ():参数
    • {}:代码段
function fn(){
	console.log('我是 fn 函数里面的代码')
}
//function:声明函数的关键字,表示接下来是一个函数了
//fn:函数的名字,我们自己定义的(遵循变量名的命名规则和密码规范)
//():必须写,用来放置参数的位置(一会我们在聊)
//{}:就是我们用来放一段代码的位置(也就是我们刚才说的盒子)
1.2、赋值式函数
  • 其实就是和我们使用var关键字是一个道理
  • 首先使用var定义一个变量,把一个函数当做值直接赋值给这个变量就可以了
  • 语法:var 函数名 = function () {};
var fun = function(){
	console.log('我是 fun 函数里面的代码')
}
//不需要在 function 后面书写函数的名字了,因为 var 已经定义了

2.函数的调用

  • 必须先定义函数才能调用,否则调用一个未定义(不存在)的函数会报错
2.1、函数调用方法

定义完一个函数后,如果函数没用被调用,那么写在{}里面的代码不会被执行,没有意义,只有调用以后才会执行

  • 函数调用语法:函数名();
//声明式函数
function fn(){
	console.log('我是 fn 函数里面的代码')
}
//调用声明式函数
fn();

//赋值式函数
var fun = function(){
	console.log('我是 fun 函数里面的代码')
}
//调用赋值式函数
fun();
2.2、调用上的区别
  • 声明式函数:调用可以在定义之前或者定义之后
//可以调用
fn();

//声明式函数
function fn(){
	console.log('我是 fn 函数里面的代码')
}

//可以调用
fn();
  • 赋值式函数:调用只能在定义之后
//会报错
fun();

//赋值式函数
var fun = function(){
	console.log('我是 fun 函数里面的代码')
}

//可以调用
fun();
  • 具体原因且看:下一篇预解析

三、函数的参数

1. 函数的参数

  • 函数的参数分为两种:形参实参
1.1 函数的形参
  • 写在函数定义阶段(形参)里面
  • 相当于一个只能在函数内部使用的变量
  • 形参的值由函数的实参来决定
function fn (a){	// a 在此处表示为形参
	console.log('我是 fn 函数里面的代码')
}
var fun = function(b){	// b 在此处表示为形参
	console.log('我是 fun 函数里面的代码')
}
1.2 函数的实参
  • 写在函数调用阶段(实参)里面
  • 为函数的形参进行赋值
  • 实参的值是一个具体的值
function fn (a){	// a 在此处表示为形参
	console.log('我是 fn 函数接收到的参数'+a);	// 12
}
var fun = function(b){	// b 在此处表示为形参
	console.log('我是 fun 函数接收到的参数'+b)	// 123
}	
fn(12);		// 12 在此处表示为实参,赋值给形参a
fun(123);	// 123 在此处表示为实参,赋值给形参b

2. 参数的作用

  • 形参的值是在调用的时候由实参决定的
function fn (a){	// a 在此处表示为形参
	console.log(a);	// a 的值取决于传入的实参
}
fn(1);	// 此时 a 的值为 1
fn(2);	// 此时 a 的值为 2
fn(3);	// 此时 a 的值为 3
  • 形参相当于函数内部可以使用的变量,在函数外部不能使用
function fn (a){	// a 在此处表示为形参
	console.log(a);	// a 的值为 12
}
fn(12);	// 12
console.log('在 fn 函数外打印形参:'+a);	//  undefined
  • 如果只有形参的话,那么在函数内部使用的值变量是没有值的
function fn (a){	// a 在此处表示为形参
	console.log(a);	// a 的值为 undefined
}
fn();	// 不传入实参(未给形参赋值)
  • 多个形参之间以,分隔,按照实参传入顺序,一一对应
function fn (a,b){	// a,b 在此处表示为形参
	console.log(a);	// a 的值为 111
	console.log(b);	// b 的值为 222
}
fn(111,222);

3. 参数的个数

3.1 形参 > 实参
  • 因为是按照顺序一一对应的
  • 所以多出来的形参就是没有值的,就是undefined
function fn (a,b,c){	// a,b,c 在此处表示为形参
	console.log(a);	// a 的值为 111
	console.log(b);	// b 的值为 222
	console.log(c);	// b 的值为 undefind
}
fn(111,222);
3.1 形参 < 实参
  • 因为是按照顺序一一对应的
  • 形参少就会拿不到实参给的值,所以在函数内部就没有办法用到这个值
function fn (a,b){	// a,b 在此处表示为形参
	console.log(a);	// a 的值为 111
	console.log(b);	// b 的值为 222
}
// 由于函数里面没有定义相应的形参去接收多余的实参,所以用不了
fn(111,222,333);
3.3 获取形参个数(length)
function funZero(){
	console.log("0个参数");
}
function funOne(a){
	console.log("1个参数");
}
function funTwo(a,b){
	console.log("2个参数");
}
console.log(funZero.length);	// 0
console.log(funOne.length);		// 1
console.log(funTwo.length);		// 2

四、复杂数据类型参数

赋值的区别

  • 之前我们知道了,基本数据类型和复杂数据类型在存储上是有区别的
  • 那么他们在赋值之间也是有区别的
  • 基本数据类型之间的赋值
let num = 10;
let num2 = num;
num2 = 200;
console.log(num);	// 100
console.log(num2);	// 200
  1. 相对于是把 num 的值复制了一份一模一样的给了num2变量
  2. 赋值以后两个在也没有关系
  • 复杂数据类型之间的赋值
var obj = {
	name : 'jack'
}
var obj2 = obj;

obj2.name = 'Rose';

console.log(obj.name);	//Rose
console.log(obj2.name);	//Rose
  1. 因为复杂数据类型,变量存储的是地址,真实内容在堆空间内储存
  2. 所以赋值的时候就相当于把obj存储的那个地址复制了一份给到了obj2变量
  3. 现在obj和obj2两个变量存储的地址一样,指向一个内存空间
  4. 所以使用obj2这个变量修改空间内的内容,obj指向的空间也会跟着改变了

传参的区别

  • 函数的参数也是赋值的之中,在函数调用的时候,实参给形参赋值
  • 和之前变量赋值的规则是一样的
  • 函数传递基本数据类型
function fn(n){
	n = 200;
	console.log(n);	//200
}

var num = 100;
fn(num);
console.log(num);	//100
  • 函数传递复杂数据类型
function fn(o){
	o.name = 'Rose';
	console.log(o.name);	//Rose
}
var obj = {
	name : 'jack'
};
fn(obj);
console.log(obj.name);	//Rose
  1. 和之前变量赋值的时候一样,把obj内存储的地址复制了一份一模一样的给到函数内部的形参o
  2. 函数外部的obj和函数内部的形参o,存储的是一个地址,指向的是一个存储空间
  3. 所以两个变量操作的是一个存储空间
  4. 在函数内部改变了空间内的数据
  5. obj看到的也是改变以后的内容

五、函数的返回值

  • return:返回的意思,其实就是给函数一个返回值中断函数

1. 中断函数

  • 当我开始执行函数以后,函数内部的代码就会从上到下的依次执行
  • 一般情况要等到函数内的代码执行完毕才会结束函数
  • return关键字就是可以在函数中间的位置提前结束这个函数,让后面的代码不在执行
function fn(){
	console.log(1);
	console.log(2);
	console.log(3);
	// 写了return以后,后面的4和5就不会继续执行了
	return;
	console.log(4);
	console.log(5);
}

//函数调用
fn();

2. 返回值

  • 函数调用本身也就是一个表达式,表达式就应该有一个值出现
  • 现在的函数执行完毕后,是不会有结果出现的
// 比如 1 + 2 是一个表达式,那么这个表达式的结果就是3
consoel.log(1+2)//3

function fn(){
	var sum = 100;
}
//fn() 也是一个表达式,这个表达式就没有结果出现
console.log(fn());	//undefined
  • return 关键字就是可以给函数执行完毕后一个结果
  • 我们在函数内部使用return 关键字可以把任何内容当做这个函数运行后的结果
function fn(){
	var sum = 100;
	return sum;
}

// 此时,fn()这个表达式执行完毕后就有结果出现了
console.log(fn())	//100

下一篇:预解析https://blog.csdn.net/qq_45677671/article/details/114988263

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐