闭包,一个老生常谈的前端问题,同时也是一个面试大概率会问到的问题。这里我综合自己在网上看到的和自己所理解的做一点小小的总结
什么是闭包
闭包就是能够读取其他函数内部变量的函数。只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
相较于其他地方的解释,百度百科的这个翻译更能让人理解、更通俗易懂。首先,闭包是函数,什么样的函数,定义在函数内部的函数。那他是怎么成为函数内部和外部连接的桥梁的呢?
首先我们来看一下这个例子:
1 function returnFoo() { 2 let name = "fire&forget"; //定义一个函数内部变量 3 function displayName() { //定义一个函数内部子函数 4 alert(name); 5 } 6 return displayName; //返回子函数 7 } 8 9 var foo = returnFoo(); //将返回的子函数赋值给foo 10 foo(); //alert("fire&forget")
在这个例子中,我们执行方法foo()时,会出现弹框并打印出name的值。但是returnFoo函数中的值,我们无法直接访问到。 在这里,displayName()方法就是我们生成的一个闭包。而在调用foo()时,我们实则调用的就是displayName()从而打印出了returnFoo函数中的name变量。因此,他实现了returnFoo函数内外部连接的作用。
看到这里,做过OOP的同学是不是觉得很熟悉?
我们再来看下一个例子:
1 let Person = function (name1, age1, sex1) { 2 let name = name1; 3 let age = age1; 4 let sex = sex1; 5 return { 6 getName: function () { 7 return name; 8 }, 9 setName: function (name1) { 10 name = name1; 11 }, 12 getAge: function () { 13 return age; 14 }, 15 setAge: function (age1) { 16 age = age1; 17 }, 18 getSex: function () { 19 return sex; 20 }, 21 setSex: function (sex1) { 22 sex = sex1; 23 }, 24 toString: function () { 25 console.log("name:" + name + ";age:" + age + ";sex:" + sex); 26 } 27 } 28 } 29 let user1 = Person("peter","23","male"); 30 user1.getAge(); //23 31 user1.setAge(18); 32 user1.getAge(); //18 33 user1.toString(); //name:perter;age:18;sex:male
这样一看,这个Person()函数不就是一个活生生的对象嘛!这个对象内涵了3个私有变量name、age、sex。不能直接访问,必须通过调用get方法访问;不能直接修改,必须通过调用set方法修改。
所以闭包最大的应用场景就是创建对象模拟私有变量/方法。
——————————————————————————————————————
至于MDN中还指出了可以用于回调,但我个人觉得不太实用。首先写出来后代码比较复杂,且解读性不强,不利于后期维护。(当然,这都是自己的一点拙见,如有错误请大家及时指出!谢谢阅读!)