JavaScript中的高阶函数和闭包

高阶函数

高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。
在这里插入图片描述

此时fn就是一个高阶函数
函数也是一种数据类型,同样可以作为参数,传递给另外一个参数使用。最典型的就是作为回调函数。

  • 举例
<script>
	//高阶函数-函数可以作为参数传递
	function fn(a, b, callback) {
		console.log(a + b);
		callback && callback();
	}
	fn(1, 2, function() {
		console.log('我是最后调用的');
	});
< / script>


变量作用域

变量根据作用域的不同分为两种:全局变量和局部变量。

  1. 函数内部可以使用全局变量。
  2. 函数外部不可以使用局部变量。
  3. 当函数执行完毕,本作用域内的局部变量会销毁。

闭包

  • 闭包( closure )指有权访问另一个函数作用域中变量的函数。简单理解就是,一个作用域可以访问另外一个函数内部的局部变量。

  • fn外面的作用域可以访问fn内部的局部变量,闭包的主要作用: 延伸了变量的作用范围。

  1. 如何产生闭包?
    当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包
  2. 闭包到底是什么?
    理解一: 闭包是嵌套的内部函数(绝大部分人)
    理解二: 包含被引用变量(函数)的对象(极少数人)
    注意:闭包存在于嵌套的内部函数中
  3. 产生闭包的条件?(充要)
    (1)函数嵌套
    (2)内部函数引用了外部函数的数据(变量/函数)
function fn1 () {
	var a = 2
	var b = 'abc'
	function fn2 () { // 执行函数定义就会产生闭包(不用调用内部函数)
		console.log(a)
	}
	fn2()
}
fn1()

情况一:将函数作为另一个函数的返回值

function fn1() {
	var a = 2
	function fn2() {
		a++
		console.log(a)
	}
	return fn2
}
var f = fn1()
f() // 3
f() // 4

情况二:将函数作为实参传递给另一个函数调用

function showDelay(msg, time) {
	setTimeout(function() {
		alert(msg)
	}, time)
}
showDelay('atguigu', 2000)

理解:

  1. 使用函数内部的变量在函数执行完后,仍然存活在内存中(延长了局部变量的生命周期)
  2. 让函数外部可以操作(读写)函数内部的数据(变量/函数)
    问题:
  3. 函数执行完后,函数内部声明的局部变量是否还存在?
    一般是不存在,存在于闭中的变量才可能存在
  4. 在函数外部能直接访问函数内部的局部变量吗?
    不能,但我们可以通过闭包让外部操作它

闭包的产生销毁

  1. 产生: 在嵌套内部函数定义执行完时就产生了(不是在调用)
  2. 死亡: 在嵌套的内部函数成为垃圾对象时
function fn1() {
	// 此时闭包就已经产生了(函数提升,内部函数对象已经创建了)
	var a = 2
	function fn2() {
		a++
		console.log(a)
	}
	return fn2
}
var f = fn1()
f() // 3
f() // 4
f = null // 闭包死亡(包含闭包的函数对象成为垃圾对象)

闭包的应用举例∶定义JS模块

  • 具有特定功能的js文件
  • 将所有的数据和功能都封装在一个函数内部(私有的)
  • 只向外暴露一个包信n个方法的对象或函数
  • 模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能
function myModule() {
	//私有数据
	var msg = 'My atguigu' //操作数据的函数
	function dosomething() {
		console.log('dosomething()'+msg.toUppercase())
	}
	function dootherthing() {
		console.log('dootherthing()'+msg.toLowerCase())
	}
	// 向外暴露对象(给外部使用的方法)
	return {
		dosomething: doSomething,
		do0therthing: dootherthing
	}
}
(function() { // 私有数据
	var msg ='My atguigu' // 操作数据的函数
	function dosomething() {
		console.log('doSomething()'+msg.toUpperCase())
	}
	function dootherthing() {
		console.log( 'dootherthing() '+msg.toLowerCase())
	}
	// 向外暴露对象(给外部使用的方法)
	window.myModule2 = {
		dosomething: doSomething,
		dootherthing: dootherthing
	}
})()

闭包缺点

  1. 函数执行完后,函数内的局部变量没有释放,占用内存时间会变长
  2. 容易造成内存泄露
    解决:及时释放
function fn1() {
	var arr = new Array [100000]
	function fn2() {
		console.log( arr. length)
	}
	return fn2
}
var f = fn1()
f()
f = null // 让内部函数成为垃圾对象-->回收闭包

访问对象属性[‘属性名’]应用场景

问题: var a = xxx,a内存中到底保存的是什么?

  • xxx是基本数据,保存的就是这个数据
  • xxx是对象,保存的是对象的地址值
  • xxx是一个变量,保存的xxx的内存内容(可能是基本数据,也可能是地址值)

问题: 什么时候必须使用[‘属性名’]的方式?

  1. 属性名包含特殊字符:-空格
  2. 变量名不确定
<script type="text/javascript">
	var p = {}
	//1.给p对象添加一个属性: content type: text/json
	// p.content-type = 'text/json'//不能用
	p['content-type'] = 'text/json'
	console.log(p['content-type'])
	//2.变量名不确定
	var propName = 'myAge'
	var value = 18
	// p.propName =value //不能用
	p[propName] = value
	console.log(p[propName])
</script>

遍历对象

for…in语句用于对数组或者对象的属性进行循环操作。

for (var k in obj) {
	console.log(k); // k变量输出得到的是属性名
	console.log(obj[k]); // obj[k]得到是属性值
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
闭包在编程有很多应用场景,以下是一些常见的例子: 1. 数据封装和私有变量:闭包可以用来创建私有变量,从而实现数据封装和保护。这在模块化编程和面向对象编程非常有用。 2. 函数工厂:闭包可以用来创建一系列相关的函数,这些函数共享相同的外部变量。这在创建类似于Python的装饰器或JavaScript高阶函数时非常有用。 3. 延迟执行和计时器:闭包可以用来实现延迟执行和定时器功能。例如,在JavaScript,setTimeout和setInterval函数使用闭包来实现延迟执行和定时器功能。 4. 记忆化(Memoization):闭包可以用来实现记忆化,即缓存函数的计算结果,以便在后续调用重用。这可以提高函数的性能,特别是在处理计算密集型任务时。 5. 事件处理和回调函数:在JavaScript等事件驱动的编程环境闭包常用于实现事件处理和回调函数。闭包可以捕获事件处理函数的上下文,使得事件处理函数可以访问其所需的外部变量。 6. 部分应用(Partial Application)和柯里化(Currying):闭包可以用来实现部分应用和柯里化,这是一种将多参数函数转换为一系列单参数函数的技术。这可以简化函数调用,使得代码更加简洁和可读。 7. 实现迭代器和生成器:在某些编程语言,例如Python和JavaScript闭包可以用来实现迭代器和生成器,这是一种用于遍历数据结构的高效方法。
最新发布
07-14

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值