文章图片
前端面试 , 必问闭包
闭包有多重要?如果你是初入前端的朋友 , 我没有办法直观的告诉你闭包在实际开发中的无处不在 , 但是我可以告诉你 , 前端面试 , 必问闭包 。 面试官们常常用对闭包的了解程度来判定面试者的基础水平 , 保守估计 , 10个前端面试者 , 至少5个都死在闭包上 。
讲解闭包时 , 我们先来看个例子
var n = 999;
function f1() {console.log(n);
f1(); // 999
上面代码中 , 函数f1可以读取全局变量n 。 但是下面例子 , 函数外部无法读取函数内部声明的变量 。
function f1() {var n = 999;
console.log(n);
// Uncaught ReferenceError: n is not defined
上面代码中 , 函数f1内部声明的变量n , 函数外是无法读取的.
如果有时需要得到函数内的局部变量 。 正常情况下 , 这是办不到的 , 只有通过变通方法才能实现 。 那就是在函数的内部 , 再定义一个函数 。
function f1() {var n = 999;
function f2() {
console.log(n); // 999
上面代码中 , 函数f2就在函数f1内部 , 这时f1内部的所有局部变量 , 对f2都是可见的 。 既然f2可以读取f1的局部变量 , 那么只要把f2作为返回值 , 我们不就可以在f1外部读取它的内部变量了吗!
闭包是什么
闭包是一种特殊的对象 。
它由两部分组成 。 执行上下文(代号A) , 以及在该执行上下文中创建的函数(代号B) 。
当B执行时 , 如果访问了A中变量对象中的值 , 那么闭包就会产生 。
在大多数理解中 , 包括许多著名的书籍 , 文章里都以函数B的名字代指这里生成的闭包 。 而在chrome中 , 则以执行上下文A的函数名代指闭包 。
我们可以对上面代码进行如下修改:
function f1(){
var a = 999;
function f2(){
console.log(a);
return f2; // f1返回了f2的引用
var result = f1(); // result就是f2函数了
result(); // 执行result , 全局作用域下没有a的定义 ,
//但是函数闭包 , 能够把定义函数的时候的作用域一起记住 , 输出999
上面的例子 , 首先有执行上下文f1 , 在f1中定义了函数f2 , 而通过对外返回f2的方式让f2得以执行 。 当f2执行时 , 访问了f1内部的变量a 。 因此这个时候闭包产生
闭包就是函数f1 ,
【饿了么|广州蓝景技术分享 — 闭包原理以及使用场景】在上面的图中 , 红色箭头所指的正是闭包 。 其中Call Stack为当前的函数调用栈 , Scope为当前正在被执行的函数的作用域链 , Local为当前的局部变量 。
JavaScript拥有自动的垃圾回收机制 , 关于垃圾回收机制 , 有一个重要的行为 , 那就是 , 当一个值 , 在内存中失去引用时 , 垃圾回收机制会根据特殊的算法找到它 , 并将其回收 , 释放内存 。
而我们知道 , 函数的执行上下文 , 在执行完毕之后 , 生命周期结束 , 那么该函数的执行上下文就会失去引用 。 其占用的内存空间很快就会被垃圾回收器释放 。 可是闭包的存在 , 会阻止这一过程 。
我们再来看个例子:
var fn = null;function foo() {
var a = 2;
function innnerFoo() {
console.log(a);
fn = innnerFoo; // 将 innnerFoo的引用 , 赋值给全局变量中的fn
function bar() {
fn(); // 此处的保留的innerFoo的引用foo();bar(); // 2
- 伊隆·马斯克|网传学习通1.7亿密码泄露!有什么补救措施?
- 6月21日消息|饿了么免单,金额少的十几元,多的有上百元
- 当24款不同的头显原型机一起呈现在眼前时|四大vr原型机面世,下一代vr头显会是什么样?
- MacBook Air|M2 MacBook Air是所有win轻薄本无法打败的梦魇,那么应该怎么选?
- 折叠屏|618已过,大浪淘沙剩下什么机型?这几款都是经典
- 华硕|大学生换笔电怎么选?12代酷睿+RTX3050独显,618换新优选它
- iPhone|还等什么iPhone 14?618返场大促看这3款真香手机,错过委屈半年
- 青岛市|孟晚舟成为华为的一把手,任正非果然反悔了,这其中发生了什么
- 华为鸿蒙系统|即将上线的鸿蒙系统3.0版本,将带来什么样的全新体验?
- 三星手机|为什么中国越来越少人用三星手机了?是哪里不好吗?