四、JS的复杂数据类型--函数(上)

函数-上

引入:

怎样洗衣服?

手动怎么洗?拿个盆,接水,放衣服,倒洗衣粉,洗,涮,拧干

挺费劲的,有没有简便的方法?

使用洗衣机,衣服放进去,倒上洗衣粉,按开关,一切就都搞定了

在生活中这样的例子有很多,大到洗衣机空调,小到水龙头剪刀。每个工具都有自己不同的功能。为了生活方便简洁,就会使用这些工具。

程序员是一群很会享受生活的群体,所以在代码中也有很多这样的工具,就是咱们今天要学习的函数。

总结:代码中工具----函数

概念:

函数就是具备某个功能的一个工具。是完成某个功能的一段代码。

大家以前有没有用过函数呀?

parseInt() alert() 这都是函数,是系统提供的,直接拿来就能用。

系统提供了很多函数,但是并不能包含所有的功能,所以有些功能需要我们自己来写----自定义函数。函数定义好以后,就可以像系统函数一样使用了,不用再重复写了。

所以经常写的代码,就写一个函数,需要的时候调一下好了。

自定义函数怎么写?

定义语法:

function 函数名(){
	代码段
}
# function是一个关键字,函数名自定义,定义规则和变量的定义规则相同

当我们定义好函数,并在页面中刷新的时候,会发现这段代码并没有被执行。因为函数定义好后,是不会自动执行的,需要我们进行调用。

函数的调用:

语法:
	函数名()

调用的语法很简单,这样我们以后还需要执行函数中的代码的时候,就不用再重写那么多的代码了,只需要简单的将原来定义好的函数进行调用即可。

// 定义函数:求两个数的和
function fn(){
    var a = 1;
    var b = 2;
    var c = a + b;
    console.log(c);
}
// 函数定义好以后,不会自动执行,需要手动调用
fn();

函数的优点:

  1. 实现了代码的可重用性
  2. 实现了模块化编程

我们在使用工具的时候,很多工具需要我们带东西进去,比如洗衣服要放衣服进去,用函数这个工具来说的话,就是需要带参数。

带参数的函数:

函数代码中会发生改变的值用变量来代替,入口是声明函数时的小括号

function zizeng(a){  // 叫做形参 - 形式上的参数
    var b = a + 1;
    console.log(b);
}

调用函数的时候,需要给参数赋值

zizeng(1); // 实参 - 实际上的参数,实参其实就是给形参赋值

获取函数的实参

函数中还有一个关键字arguments可以获取到所有的实参

function css(){
	// 打印实参
	console.log(arguments);
	// 打印实参的个数
	console.log(arguments.length);
}
css("width","100px");

效果:

获取实参和个数

在这里插入图片描述

如果有形参的话,也是一样的,通过下标取到其中的每一个值

匿名函数(赋值式的函数)

概念:顾名思义,匿名函数就是没有名字的函数。

定义:

语法:
	function(){
        代码段
	}

当然匿名函数也可以传递参数。

调用:匿名函数的调用是在定义的时候调用

语法:
	(function(形参){
        代码段
	})(实参)

很简单,就是在大括号后面加小括号就是调用。

(function(a,b){
    var c = a + b;
    document.write(c);
})(1,2);

也可以将匿名函数赋值给变量,调用的时候使用变量名来调用。

语法:
# 定义
	var fun = function(){
        代码段
	}
# 调用
	fun()

例:

var fun = function(a,b){
    var c = a + b;
    document.write(c);
}
fun(1,2);

通过事件来调用匿名函数

<style>
#myid{
	width:200px;
	height:200px;

	background:#f00;
}
</style>
<body>
	<div id="myid"></div>
</body>
<script>
var oDiv = document.getElementById("myid");
oDiv.onclick=function(){
	alert(123);
}
</script>

变量的声明提升

浏览器中有一段程序专门用来解析js代码, 叫做js解析器。js解析器在执行js代码的时候,分两步进行:

  1. 预解析js代码

    预解析的过程,就是查找代码中的var和function这两个关键字,找到以后,将变量和函数存到了一个地方,就叫仓库吧,并给他们赋一个初始值,变量的初始值为undefined,函数的初始值为代码段。

  2. 开始按顺序一行一行解读代码

    解读代码的时候,仓库中的变量和函数的值会随着代码的解读而发生变化,也就是变量的赋值和函数的调用。

预解析分为变量的预解析和函数的预解析,也就是代码在执行之前先进行解析,将变量和函数的声名放在当前作用域的最前面。

console.log(a); // 因为变量a没有声名过,所以会报错

test(); // 函数未定义,所以报错

但是在打印之后声名过变量的话,情况就不一样了。

// 变量预解析
console.log(a); // 因为变量a在执行之前进行了预解析,也就是已经放到内存中了,只是没有值,所以是undefined
var a = 1;
/* 预解析相当于下面的过程 */
var a; // 将变量的声名放到当前作用域的最前面
console.log(a);
a = 1;

// 函数预解析
test(); // 结果:123   代码在执行之前经过预解析,将函数的内容放到了内存了,所以在下面的定义函数也能调用执行
function test(){
	console.log(123);
}
/* 预解析过程如下: */
function test(){ // 将函数声名放到当前作用域的最前面
	console.log(123);
}
test();


案例:

// 1.匿名函数赋值给变量
fn();//报错:fn is not a function
var fn = function(){
    console.log(123);
}
// 2.函数内部的变量预解析
function test(){
    console.log(a);
    var a = 10;
}
test();//undefined

总结:

  1. 用var关键字声名的变量,将变量的声名提升到当前作用域的最前面,赋值不提升
  2. 自定义的函数整体提升到当前作用域的最前面
  3. 函数同名,后面的会覆盖前面的
  4. 在变量提升阶段,变量和函数同名,函数优先提升
  5. 在执行阶段,变量和函数同名,变量优先提升

面试题:

//1. 
var num = 10;
fn1();//undefined
function fn1() {
  console.log(num);
  var num = 20;
}
说明:函数fn()执行时,函数体内声名的变量num提升到当前作用域的最前面,但赋值未提升,所以打印undefined
------------------------------------------------------------------------------------
//2. 
var a = 18;
fn2();//18   9
function fn2() {
    var b = 9;
    console.log(a);
    console.log(b);
}
说明:这题答案很直观,函数fn2()执行时,函数体首先提升到最前面,函数体内的变量a在函数体外已经定义并赋值为18,所以先打印18,变量b在函数体内,执行打印前已经定义并赋值为9,所以打印完a后,b打印是9
------------------------------------------------------------------------------------
//3.
fn3();//9  9  9
console.log(c);//9
console.log(b);//9
console.log(a);//报错:a is not defined
function fn3() {
  var a = b = c = 9;
  console.log(a);
  console.log(b);
  console.log(c);
}

说明:函数fn3()在执行时a,b,c都是9这个很好理解,函数执行后函数外面打印c和b时,因为c和b在函数内部都被赋过值9,但未被定义。所以js会自动定义变量b和c,所以打印也是9.但是函数外面打印a的话,a在函数内部被var定义并赋值了,所以此时在函数外面打印a就会报错: a is not defined
------------------------------------------------------------------------------------
//4. 思考题
var a = 4;
console.log(a);//4
a = 6;
console.log(a);//6
function a() {
    console.log('哈');
}
a();//报错:a is not a function
a = 10;//未被执行
console.log(a);//未被执行
说明:首先函数体会被提升到最前面,但未被执行,然后下面就var定义并赋值了变量a为4,所以第一个打印的是4,后面a又被重新赋值为6,所以第二次打印a为6,然后下面函数体又被提升到最上面去了,就剩函数的执行代码a()了。而此时a已经被赋值为6,所以执行的就是6()。但6是一个数字不能被执行,所以报错:a is not a function。报错后下面代码将不再被执行。所以结果就是46, 报错:a is not a function

形参和实参

声明函数时候带进去的那个参数叫形参

调用函数的时候给形参进行赋值的实际值是实参

不是所有的程序的结果都需要输出在页面中,有时候,我们只是想让这一段代码得出一个结果,后续代码得到这个结果后进行后续处理。那么上面的函数显然已经不适用了。我们需要使用函数的返回。

带返回值的函数

语法:
	function 函数名(){
        return 返回的结果
	}

将结果返回的关键字是return,这样可以将函数运算的结果返回给调用者

// 定义一个让指定数字递增的函数
function increase(x){ // 带有参数的函数
	var y = x + 1;
	return y
}
// 让2递增,得到结果赋值给变量3
var a = increase(2);
document.write(a%2); // 1
// 让5递增,得到结果赋值给变量b
var b = increase(5);
alert(b/2); // 3
// 让10递增,得到结果赋值给变量c
var c = increase(10); 
console.log(c+a-b); // 8

带有返回值的函数,当调用函数的时候得到一个结果,这个结果可以参加运算,也可以进行赋值。

带有返回值的函数,当函数执行到return关键字的时候,函数就终止了,在return后面的代码不会运行。

// 定义一个让指定数字递增的函数
function increase(x){ // 带有参数的函数
	var y = x + 1;
	return y
    // 下面的代码不会被执行
	y += 2;
	alert(y);
}
// 让2递增,得到结果赋值给变量3
var a = increase(2);
document.write(a);

return的作用:

  1. 终止代码继续运行
  2. 在函数中返回一个内容

函数的嵌套

函数的嵌套就是在函数中调用函数:

// 求数组中所有元素的平均数
/*
分析:
	1.先求和
	2.再求平均数
 */
// 求和函数
function sum1(arr) {
	var s = 0;
	for(var i in arr){
		s += arr[i];
	}
	return s;
}
// 求平均数函数
function avg1(arr) {
	var sum = sum1(arr);
	var length = arr.length;
	var a = sum/length;
	return a;
}
// 调用
var arr = [1,6,9,7,2];
var avg = avg1(arr);
console.log(avg);

函数的调试

示意图

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值