什么是闭包
闭包是指函数以及其相关的引用环境组合而成的实体。简单来说,闭包是一个函数和其周围的状态(词法环境)的集合体。
要形成闭包,通常需要满足以下两个条件:
1.在一个函数内部定义了另一个函数。
2.内部函数引用了外部函数的变量。
js实现闭包代码如下:
function outerFunction() {
var x = 10;
function innerFunction() {
console.log(x);
}
return innerFunction;
}
var closure = outerFunction();
closure(); // 输出结果为10
在上述示例中,outerFunction 是外部函数,内部函数 innerFunction 引用了外部函数的变量 x。通过调用 outerFunction(),返回了一个闭包函数 closure,可以通过调用 closure() 来访问闭包函数并输出结果。在这个闭包中,innerFunction 保持了对 outerFunction 的词法环境的引用,因此可以访问到 x 的值。
闭包的优缺点
优点:
1.数据封装:闭包可以隐藏内部变量,只暴漏特定接口,实现数据的私有化和封装性,保护数据不受外部干扰。
2.记忆效应:闭包内的变量可以在函数调用结束后仍然保存存在,因而可以保存状态,记住上下文,实现类似于“记忆”效果,方便实现某些功能,如缓存、计数器等。
3.延长作用域链:闭包可以扩展函数的作用域链,使得内部函数可以访问外部函数的变量,灵活性更高。
缺点:
1.内存泄露:由于闭包会将他引用的外部变量保存在内存中,如果闭包被长时间持有且未释放。会导致内存泄露的问题。
2.性能消耗:闭包会占用较多的内存空间和计算资源,因为需要维护额外的作用域链和外部变量的引用。
3.对象状态的不确定性:闭包内的变量可能会被外部修改,这可能导致不可预料的结果。
闭包的应用场景
1.实现模块化:闭包可以将变量和函数封装在一个独立的作用域中,实现模块化开发,避免全局命名冲突。
2.数据缓存和记忆化:利用闭包的记忆效应,可以实现一些缓存计算、避免重复计算的功能,提高代码性能。
3.封装私有变量:通过闭包,可以创建具有私有变量和方法的对象,实现面向对象的封装性。
4.事件处理和回调:在异步编程中,可以使用闭包来保存异步操作的上下文和状态,以便在回调函数中使用
事件循环的理解
事件循环是一种处理异步任务的机制,它在JavaScript引擎中运行。
JavaScript是单线程执行的,就是一次只能执行一个任务,但是这并不就是说单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环。
js的执行顺序
1.js是从上到下一行一行执行。
2.如果某一行执行报错,就不会执行下面的代码了。
3.js会执行同步代码,后执行异步代码。
事件循环的执行过程
先执行同步代码,调用栈执行后直接出栈。
在执行异步代码,接收到异步代码后,先放到web api中等待,随后等到合适的时候放入回调队列(callbackQueue),等到调用栈空时eventLoop开始工作。
记住微任务先执行,宏任务后执行。
微任务在DOM渲染前触发,宏任务在DOM渲染后触发
console.log('我是任务1');
setTimeout(()=>{
console.log('我是任务2');
});
Promise.resolve().then(()=>{
console.log('我是任务3');
})
console.log('我是任务4');
在上述代码块中,任务1和任务4是同步代码所以先执行,任务3为微任务,随后执行,任务2是宏任务最后执行。
事件循环的应用场景
1.用户交互:他可以响应用户的交互操作,就像点击,滚动或者拖拽等。他通过监听DOM事件,然后将对应的回调函数添加到队列中,在下一个事件循环周期中执行以更新页面状态或执行相应的逻辑。
2.异步请求:使用XMLHttpRequest、Fetch或者基于XHR封装的第三方库就像axios发送异步请求获取数据。通过将请求的回调函数或Promise的then()方法添加到任务队列,响应返回之后,在下一个事件循环周期中执行相应的回调函数来处理数据。
3.定时器:使用 setTimeout 和 setInterval 方法设置定时器,可以在指定的延迟时间过后执行特定的代码或周期性地执行代码。
js类型校验的方法
1.typeof操作符:它可以检查一个变量的类型,它返回被检查变量的数据类型,是以字符串形式展现。如“string”,“number”,“function”,“undefined”等,注意typeof对null和对象类型(包括数组)会返回“object”。
2.instanceof:它是检查一个对象是否数据某个类或者构造函数,如,obj.instanceof===Array,可以检查obj是否为Aray类型。
3.constructor:都知道JavaScript对象都有一个constructor属性,是来指向创造该对象的构造函数。通过obj.constructor ===Array可以检查obj是否为Array类型的对象
4.Array.isArray:它可以确定一个对象是否为数据,它返回一个布尔值,表示对象是否为数组类型。