简介
闭包现象是JS中一个特色但是又比较难的知识点,此外很多高级的应用程序都是依靠闭包来实现的,所以它的重要性不言而喻。简单点来说,闭包的作用就是把函数的内部和外部建立起联系。对于初学者而言呢,我们要先学会读懂代码,再去慢慢尝试自己写闭包。想要更好的理解闭包,就得理清JS中变量的作用域问题
-
全局变量
1.函数外部定义,全局范围有效
2.始终保存在内存中,随着程序的执行完毕(页面关闭)而销毁
-
局部变量
1.函数内部定义,在函数内部有效
2.当函数执行结束后,就会销毁
闭包的主要用途
-
让函数外部能够获取到函数内部的变量
-
让函数内部的变量始终保存在内存中
实例:
//让函数外部能够得到函数内部的变量
function outside(){
var num1=10
function inside(){
return num1
}
return inside
}
var n=outside()() //相当于var a=outside()接收返回的inside,var n=a()接收返回的num1;
console.log(n)
//让函数的局部变量一直存在于内存当中
function fn1(){
var num1=10
add=function(){ //这里的add是不能直接访问num的,每调用一次add方法都会找上一次的num值,再做++操作
num1++
console.log(num1)
console.log("add")
}
function fn2(){
console.log(num1)
}
return fn2
}
闭包存在的缺点
闭包可以让函数外部拿到函数内部的变量,也能将函数内部的变量始终保存在内存中。 这是闭包的优点,也是它的缺点。 因为一旦滥用闭包就会让内存消耗变大,情况严重时可能会造成内存泄露。
对应的解决办法
使用面向对象的方法进行代码的编写,将需要使用的函数和变量尽量封装到一个对象中去
记录的几个比较经典的面试题:
面试题1
var name ='window'
var obj={
name:'obj'
getName:function(){
return function(){
return this.name
//就是考察this的指向问题,确定作用域,对象是没有作用域的,只有函数和<script>有作用域
}
}
}
alert(obj.getName()()) //window
面试题2
var name='window'
var obj={
name:'obj'
getName:function(){
var _this=this //这一步零时存储了this的指向,(对象方法,指向对象)
return function(){
return _this.name
}
}
}
alert(obj.getName()()) //obj
面试题3
function getSum(num1){
return function(num2){
return num1+num2 //函数自身没有num1所以会往上层找,找到num1做加法运算
}
}
let n=getSum(5)(10)
console.log(n) //15
附加题
function fn(n,o){
console.log(n,o)
return {
fn:function(m){
return fn(m,n)
}
}
}
var a = fn(0); //0,undefined
a.fn(1); //1,0
a.fn(2); //2,0
a.fn(3); //3,0
var b = fn(0).fn(1).fn(2).fn(3);//链式调用,也可以拆写
等价于:var b=fn(0) //0,undefined
var c=b.fn(1) //1,0
var d=c.fn(2) //2,1
var e=d.fn(3) //3,2
var c = fn(0).fn(1);//拆写成,var a=fn(0);var b=a.fn(1) 1,0
(注意:我这里就的结果就少了一个0,undefined,虽然它写的是链式调用的方式,但是我们要清楚执行的流程,和每一步的返回值,不能遗漏)
c.fn(2); //相当于b.fn(2) 2,1
c.fn(3); //相当于b.fn(3) 3,1