JavaScript - 函数 and 循环绑定

目录

一、函数

1、创建函数

ES5

ES6

匿名函数

2、函数的调用

3、函数的参数

个数不需要统一(多舍,少undefined)

可以任意位置具有默认值

通过 ... 接收多个值

4、返回值

5、函数回调

- 传输数据 普通传输 and 回调传输

- 钩子函数:系统中默认存在回调

- 钩子函数获取网页点击坐标数据等

6、闭包:函数的嵌套

- 提升作用域:全局定义,局部赋值(强烈不推荐使用,存在变量不安全的风险)

- 闭包解决局部变量生命周期:局部变量绑定闭包函数,闭包函数存在,局部变量存在

二、循环绑定

- 闭包解决变量污染

- ES6语法简单处理变量污染:块级作用于不存在全局变量的重命名。

- 对象属性解决变量污染:对象思想,利用属性的局部性和临时性保存数据。


一、函数

1、创建函数

  • ES5

function 函数名 (参数列表) {
    函数体;
}
​
var 函数名 = function (参数列表) {
    函数体;
}
  • ES6

let 函数名 = (参数列表) => {
    函数体;
}
  • 匿名函数

(function (参数列表) {
    函数体;
})
​
// 匿名函数需要自调用
(function (参数列表) {
    函数体;
})(参数列表);

2、函数的调用

  • 函数名(参数列表)

    function myFunction()
    {
    var x=5;
    return x;
    }
    
    myFunction()
    

     


3、函数的参数

  • 个数不需要统一(多舍,少undefined)

function fn (a, b, c) {
    console.log(a, b, c);  // 100 undefined undefined
}
fn(100);
​
function fn (a) {
    console.log(a)  // 100
}
fn(100, 200, 300)  // 200,300被丢弃
  • 可以任意位置具有默认值

function fn (a, b=20, c, d=40) {
    console.log(a, b, c, d);  // 100 200 300 40
}
fn(100, 200, 300);
  • 通过 ... 接收多个值

function fn (a, ...b) {
    console.log(a, b);  // 100 [200 300]
}
fn(100, 200, 300);
// ...变量必须出现在参数列表最后

4、返回值

function fn () {
    return 返回值;
}
// 1.可以空return操作,用来结束函数
// 2.返回值可以为任意js类型数据
// 3.函数最多只能拥有一个返回值 若:return data,a;则只返回后者a

5、函数回调

在一个函数(fn)中,满足条件情况下,调用另外一个函数(func)作为参数
:func函数 是 fn函数 的参数(函数作为函数参数传入)

// 回调的函数
function callback(data) {}
// 逻辑函数
function func(callback) {
    // 函数回调
    if (callback) callback(data);
}
​
// 函数回调的本质:在一个函数中(调用函数),当满足一定条件,调用参数函数(回调函数)
// 回调函数作为调用函数的参数传入
// 回调函数通过参数将调用还是内部数据传出

<script type="text/javascript">
	// 解决问题:
	// 请求数据 => 数据(return | 函数回调) => 外界

	function a_fn(data) {
		console.log('a_fn');
		// 如果要使用数据,那么定义形参接收参数
		console.log(data);
	}

	function b_fn(a_fn) {
		var data = "b_fn 的 数据";
		console.log('b_fn');
		// 条件: a_fn有值(有函数实现体)
		if (a_fn) {
			// 调用参数函数
			a_fn(data);
		}
	}
	b_fn(a_fn);

	// 1.一个函数(函数名)作为另外一个函数的参数
	// 2.满足一定的条件,调用参数函数
	// 3.形成了函数回调,回调的函数可以获取调用函数的局部变量(将数据携带出去)
</script>

- 传输数据 普通传输 and 回调传输

<!-- 普通函数实现数据的传输 -->

<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<title>数据请求</title>
</head>
<body>
	
</body>
<!-- 外部要接收数据 -->
<!-- 函数callback接受数据传输 -->
<script type="text/javascript">
	var callback = function (data,a) {
		// 使用数据
		console.log(data);
                console.log(a);
	}
</script>


<!-- 模拟请求数据 -->
	<script>
		var a_fn = function(){
			console.log("开始请求数据...");
			// ...
			var data = [1, 2, 3, 4, 5];
                        a = 123
			console.log("数据请求完毕!!!");
			return data,a;
		}
// 模拟接受数据数据 
		callback(a_fn())

	</script>
	
</html>

 

<!-- 回调函数模拟数据传输 -->
<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<title>数据请求</title>
</head>
<body>
	
</body>
<!-- 外部要接收数据 -->
<!-- 1.外部给内部提供回调函数(函数名callback) -->
<!-- 2.内部将数据反馈给外部回调函数.外部就可以使用内部数据 -->

<script type="text/javascript">
	var callback = function (data,a) {
		// 使用数据
		console.log(data);
                console.log(a);
	}
</script>


<!-- 请求数据 -->
<script type="text/javascript">
	try {
		// 采用匿名函数自调用请求数据,不存在返回值
		(function (callback) {
			console.log("开始请求数据...");
			// ...
			var data = [1, 2, 3, 4, 5];
                        a = 123
			console.log("数据请求完毕!!!");
			// 如果回调函数存在,那么回调对应的函数,并将数据携带出去
			if (callback) {
				callback(data,a);
			}
		})(callback)
		// 请求数据完毕之后,需要让外界获取请求的数据:
		// 1.函数返回值: 函数的自调用,不存在其他调用者,也就无法获取函数的执行结果
		// 2.函数回调
	} catch (err) {

	}
</script>
<!-- 外部要接收数据 -->
	
</html>

数据传输方式总结:

  • 普通函数进行传值,使用return返回,并且只能返回一个值
  • 回调函数传值,使用匿名函数,可以直接传输多个值

 

- 钩子函数:系统中默认存在回调

<script type="text/javascript">
	// 通常情况下,我们的页面标签存不存在点击事件? => 存在
	// 点击事件触发后,可不可以对外传送数据 => 可以,eg:点在页面的什么位置
	// 系统已经书写好了这种函数回调,但是没有回调体,回调体(回调函数)由普通开发者提供

	// 钩子:满足条件情况下被系统回调的函数(方法),称之为钩子函数(方法) <=> 回调函数
	document.onclick = function (a, b , c) {
		console.log("点击事件");
		console.log(a, b , c);
	}
</script>

- 钩子函数获取网页点击坐标数据等

document.onclick = function (event) {
		console.log("点击事件");
		console.log(event);
		console.log(event.clientX);
		console.log(event.clientY);
		
	}


6、闭包:函数的嵌套

闭包: 函数的嵌套定义,内层函数就是闭包


闭包产生的原因: 

  • 需求:外部使用,函数局部作用域内的参数, -- 解决方法:返回值 | 函数回调 | 闭包 | 提升作用域
  • 需求:外部,另一个函数中使用该函数体内的局部变量 -- 解决方法: 函数回调 | 闭包
  • 需求:不能使用函数回调(函数已有固定参数,或不能拥有参数),只能将函数定义到拥有局部变量函数的内部 => 闭包
  • 闭包总结:内部函数要使用,外部函数的局部变量

 

闭包函数的优点:

  • 外部函数不需要强制拥有参数以及返回值
  • 外部函数的局部变量也无需提升作用域,可以保证参数的安全性
  • 内部函数不需要强制拥有参数与返回值,便可以直接使用外部函数的局部变量
  • 局部变量的持久化(提升局部变量的生命周期)
  • 变量污染(页面标签循环绑定)
function outer() {
    var data = {}
    function inner() {
        return data;
    }
    return inner;
}
​
// 闭包目的:不允许提升变量作用域时,该函数的局部变量需要被其他函数使用
// 闭包本质:函数的嵌套,内层函数称之为闭包
// 闭包的解决案例:①影响局部变量的生命周期,持久化局部变量;②解决变量污染

function a_fn() {
    var data = [1, 2, 3, 4, 5];
    // 闭包
    function b_fn() {console.log('>>>', data);}
    b_fn();}
a_fn();

- 提升作用域:全局定义,局部赋值(强烈不推荐使用,存在变量不安全的风险)

// 提升作用域
var a;  // 作用域被提升
function fn() {
    a = 10;  // 局部变量 => 在外部定义
}
fn();
// 外部使用局部变量: 返回值 | 函数回调 | 闭包 | 提升作用域
console.log(a);

- 闭包解决局部变量生命周期:局部变量绑定闭包函数,闭包函数存在,局部变量存在

生命周期:就是一个变量在程序执行过程中的“有效期”,比如说全局变量,那它在整个程序执行过程中都有效,及它的生命周期是整个程序执行过程,而对于一些在函数里定义的局部变量,它只是在调用函数是有效,函数调用结束,它的生命周期也完了。

<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<title>局部变量生命周期</title>
</head>
<body>
	局部变量生命周期
</body>
<script type="text/javascript">
	function outer() {
		// 方法执行完毕后,数据data就会被销毁
		var data = [1, 2, 3, 4, 5];
		console.log(data);
		// 若通过闭包函数绑定局部变量,则可保证局部变量不被销毁
		function inner() {
			return data;
		}
		// 数据被inner操作返回,inner属于outer,属于需要outer将inner返回出去(跟外界建立起联系)
		return inner;
	}
	// 将局部变量生命周期提升于inner函数相同,inner存在(即inner未被调用),局部变量data就一直存在
	var inner = outer();
        //执行inner 生命周期结束
	console.log(inner());

</script>
</html>

 

 

二、循环绑定

循环绑定产生的变量污染问题的解决方法:

  • ES5下闭包解决(优先推荐)
  • ES6的块级作用域:let定义循环内变量
  • 对象属性解决

- 闭包解决变量污染

变量污染:全局变量的重命名覆盖问题,例:a=1; a=2则后者覆盖前者造成变量污染问题

循环绑定造成的变量污染问题(本质是var定义的全局变量循环,赋值):

<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<title>闭包解决变量污染</title>
	<style type="text/css">
		ul {
			margin: 0;
			padding: 0;
			list-style: none;
		}
		li {
			width: 80px;
			height: 35px;
			background-color: pink;
			border-radius: 5px;
			float: left;
			margin-left: 3px;
		}
	</style>
</head>
<body>
	<ul>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
	</ul>
</body>
<script type="text/javascript">
	// 需求:点击li,打印li在ul中的索引 => 0, 1, 2, 3, 4
	var lis = document.querySelectorAll('ul li');
	for (var i = 0; i < lis.length; i++) {
		lis[i].onclick = function () {
			alert(i);
		}
	}

</script>
</html>

解决方法(闭包):本质是将var定义的全局变量i,变成闭包内的局部变量进行存储、

<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<title>闭包解决变量污染</title>
	<style type="text/css">
		ul {
			margin: 0;
			padding: 0;
			list-style: none;
		}
		li {
			width: 80px;
			height: 35px;
			background-color: pink;
			border-radius: 5px;
			float: left;
			margin-left: 3px;
		}
	</style>
</head>
<body>
	<ul>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
	</ul>
</body>
<script type="text/javascript">
	// 需求:点击li,打印li在ul中的索引 => 0, 1, 2, 3, 4
	// 1.lis 
	var lis = document.querySelectorAll('ul li');
	// 2.循环绑定
	for (var i = 0; i < lis.length; i++) {
		// 解决的原理:一共产生了5个外层函数,存储的形参i的值分别是0, 1, 2, 3, 4
		// 内层函数也产生了5个,且和外层函数一一对应,打印的i就是外层函数的形参i

		// 外层函数
		(function (i) {
			// 内层函数:闭包
			lis[i].onclick = function () {
				alert(i)
			}
		})(i)	
	}
	console.log(i); 
</script>
</html>

 

- ES6语法简单处理变量污染:块级作用于不存在全局变量的重命名。

!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<title>块级作用域解决循环绑定</title>
	<style type="text/css">
		ul {
			margin: 0;
			padding: 0;
			list-style: none;
		}
		li {
			width: 80px;
			height: 35px;
			background-color: pink;
			border-radius: 5px;
			float: left;
			margin-left: 3px;
		}
	</style>
</head>
<body>
	<ul>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
	</ul>
</body>
<script type="text/javascript">
	// ES6语法中支持块级作用域
	let lis = document.querySelectorAll('li');
	for (let i = 0; i < lis.length; i++) {
		lis[i].onclick = function () {
			alert(i)
		}
	}
</script>
</html>

- 对象属性解决变量污染:对象思想,利用属性的局部性和临时性保存数据。

<script type="text/javascript">
	var lis = document.querySelectorAll('li');
	for (var i = 0; i < lis.length; i++) {
		lis[i].index = i;  
		lis[i].onclick = function () {
			// var temp = lis[i].index; // lis[i]中的i一样存在变量污染
			alert(this.index)  // 当前被点击的li
		}
	}
</script>

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值