js面试闭包完美回答 ,JavaScript闭包函数

本文目录

Javascript闭包函数


提问

该问题可能描述不清,建议你重新提问
Javascript的闭包是什么意思 有什么用
我有更好回答

PHP交流者之家
电脑网络认证团队  推荐于 2017-09-06
一、什么是闭包?
“官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
相信很少有人能直接看懂这句话,因为他描述的太学术。我想用如何在Javascript中创建一个闭包来告诉你什么是闭包,因为跳过闭包的创建过程直接理解闭包的定义是非常困难的。看下面这段代码:
function a(){
var i=0;
function b(){
alert(++i);
}
return b;
}
var c = a();
c();
这段代码有两个特点:
1、函数b嵌套在函数a内部;
2、函数a返回函数b。
这样在执行完var c=a()后,变量c实际上是指向了函数b,再执行c()后就会弹出一个窗口显示i的值(第一次为1)。这段代码其实就创建了一个闭包,为什么?因为函数a外的变量c引用了函数a内的函数b,就是说:
当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。
我猜想你一定还是不理解闭包,因为你不知道闭包有什么作用,下面让我们继续探索。

js面试闭包完美回答
,JavaScript闭包函数图1

js闭包面试题


//首先你的代码等价于下面的代码
function getFuns() {
    var funs = [];
    var i = 0;
    funs[i] = function() {
        console.log(i);
    };
    i = 1;
    funs[i] = function() {
        console.log(i);
    };
    i = 2;
    funs[i] = function() {
        console.log(i);
    };
    i = 3;
    return funs;
}
var arr = getFuns();
arr[0]();
arr[1]();
arr[2]();
//无论哪调用function(){console.log(i);};这个函数,那个i都只有那一份,
//虽然i的作用域在getFuns里面,但当你在外面用这种方式间接使用到i时,
//它的生命周期被延长。
//这样输出2 2 2
function getFuns() {
    var funs = [];
    for (var i = 0; i < 3; i++) {
        var a = i;
        funs[i] = function() {
            console.log((a))
        };
    }
    return funs;
}
var arr = getFuns();
arr[0]();
arr[1]();
arr[2]();
//这样就可以输出0 1 2
function getFuns() {
    var funs = [];
    for (var i = 0; i < 3; i++) {
        let a = i;//或者const a = i;
        funs[i] = function() {
            console.log((a))
        };
    }
    return funs;
}
var arr = getFuns();
arr[0]();
arr[1]();
arr[2]();
//这样也可以输出0 1 2
function getFuns() {
    var funs = [];
    for (var i = 0; i < 3; i++) {
        funs[i] = (function(x) {
            return function() {
                console.log(x)
            };
        })(i);
    }
    return funs;
}
var arr = getFuns();
arr[0]();
arr[1]();
arr[2]();
//

js面试闭包完美回答
,JavaScript闭包函数图2

js闭包面试题经典


主要问题在于,自执行函数没有形参i,如果加一个形参i,输出的就是0-4了。如这样


for(var i =0;i<5;i++){
(function(i){
setTimeout(function(){
console.log(i)
},i*1000)
})(i)
}

这就是作用域的问题,for循环每执行一遍,都会生成一个异步函数setTimeout,由于这个时候是同步的,自执行函数里边的i,读取的就是每次for循环的i,所以每次执行相差1秒。然后js是单线程的,setTimeout需要等for执行完之后执行。这时候,for循环执行完使得i的值变为5,而自执行函数没有形参,setTimeout回调函数读的变量是自执行函数外的变量i,所以输出为5。也就是每隔一秒输出一个5。


你可以试着把5变成更大的数,也是一样的,输出的就是这个数。


js面试闭包完美回答
,JavaScript闭包函数图3

彻底理解js中的闭包


要理解闭包,首先必须理解Javascript特殊的变量作用域。
变量的作用域无非就是两种:全局变量和局部变量。
Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。
Js代码
  var n=999;
  function f1(){
    alert(n);
  }
  f1(); // 999
另一方面,在函数外部自然无法读取函数内的局部变量。
Js代码
  function f1(){
    var n=999;
  }
  alert(n); // error
这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!
Js代码
  function f1(){
    n=999;
  }
  f1();
  alert(n); // 999
--------------------------------------------------------------------------------------------------------
二、如何从外部读取局部变量?
出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。
那就是在函数的内部,再定义一个函数。
Js代码
  function f1(){
    n=999;
    function f2(){
      alert(n); // 999
    }
  }
在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1 就是不可见的。这就是Javascript语言特有的“链式作用域”结构(chain scope),
子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!
Js代码
  function f1(){
    n=999;
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999
--------------------------------------------------------------------------------------------------------
三、闭包的概念
上一节代码中的f2函数,就是闭包。
各种专业文献上的“闭包”(closure)定义非常抽象,很难看懂。我的理解是,闭包就是能够读取其他函数内部变量的函数。
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。
所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

js面试闭包完美回答
,JavaScript闭包函数图4

以上就是关于js面试闭包完美回答 ,Javascript闭包函数的全部内容,以及js面试闭包完美回答 的相关内容,希望能够帮到您。

上一篇 2022年05月22日14时15分08秒
下一篇 2022年05月22日14时29分58秒

相关推荐

  • 特殊疑问词在前面的用法

    特殊疑问词在英语中起引导作用,通常放在句首。"What"用于询问事物名称、定义或数量;"Who"用于询问人物身份或行为;"Where"用于询问地点或位置;"When"用于询问时间或时间段;"Why"用于询问原因或目的。掌握特殊疑问词的用法有助于更好地理解和表达英语。 What What通常用来询问事物的名称、定义、或者是数量等信息。例如: What is your name?(你叫什么名字?) W…

    2024年01月12日
    16
  • 语法填空形容词副词

    掌握形容词和副词的用法对英语学习者至关重要。形容词通常用来描述名词或代词的特征,而副词通常用来描述动词、形容词或其他副词的特征。有些形容词也可以用作副词。在语法填空时,应根据句子的语境来判断应该填写形容词还是副词,并注意词性转换的问题。通过不断的练习和积累,我们可以更加熟练地掌握语法填空中形容词和副词的使用。 首先,形容词通常用来描述名词或代词的特征,例如“beautiful”(美丽的),“sma…

    2024年01月13日
    16
  • 一般过去时动词特殊变化

    英语的一般过去时动词变化规则通常简单,如在动词原形后加-ed,但有些动词变化特殊。以-e结尾的动词加-d,以辅音+y结尾的动词将y变为i再加-ed,以重读闭音节且末尾只有一个辅音字母的动词双写辅音字母再加-ed。还有一些常见的不规则动词需要记住。通过大量阅读和语言练习,以及使用在线工具和应用程序,可以熟悉和掌握这些变化。 动词变化规则 以-e结尾的动词,在一般过去时中直接加-d即可。例如:love…

    2024年01月12日
    16
  • 怎样判断单句复句

    判断英语句子是单句还是复句可以从三个方面进行:句子结构、连词和句子意思。单句通常是主语+谓语+宾语的结构,而复句包含主从句和连接词。复句中的连接词包括引导从句的连词,如although、because、while等。如果句子中包含两个以上的主谓宾结构,那么它就是复句。 1. 从句子结构判断 首先,可以从句子的结构来判断它是单句还是复句。单句的结构通常是主语+谓语+宾语,而复句则包含了主从句之间的连…

    2024年01月13日
    16
  • 英语中的介词指什么

    介词是英语语法中的重要部分,用于表示名词或代词与其他词之间的关系。常见的用法包括表示时间(如at noon)、地点(如at home)、方向(如go to school)、方式(如write with a pen)、原因(如because of the rain)和目的(如study for the exam)。熟练掌握介词的用法有助于更好地理解和运用英语。 表示时间:例如,at、in、on等,用…

    2024年01月13日
    16
  • 两个双重否定句例子

    双重否定句中使用两个否定词,可能导致句意混淆。例如,“我没有没有钱”应改为“我没有任何钱”,“我不能几乎等待聚会了”应改为“我非常期待聚会”。在日常生活中,应避免使用双重否定句,以免造成歧义或误解。 例子一 原句:I don't have no money. 这句话的字面意思是“我没有没有钱”,但实际上它的意思是“我没有钱”。这是因为“don't”和“no”都是否定词,它们的叠加使得这个句子的意思…

    2024年01月13日
    16
  • 什么叫疑问词

    疑问词是英语中的特殊词汇,用于提问和获取信息,包括"What"(什么),"Where"(哪里),"When"(何时),"Who"(谁),"Why"(为什么)和"How"(如何)。疑问词的选择和使用根据问题的需要而变化,是学习和使用英语的重要部分。 常用的疑问词包括: What (什么) Where (哪里) When (何时) Who (谁) Why (为什么) How (如何) 这些疑问词可以用…

    2024年01月13日
    16
  • 五个人称代词

    英语中的五个常用人称代词包括“I”(我)、“you”(你)、“he”(他)、“she”(她)和“it”(它)。这些代词在主格、宾格和所有格中有不同的形式和用法,掌握这些代词可以更好地理解和运用英语。 下面介绍英语中五个常用的人称代词,分别是:I、you、he、she和it。 1. I I是英语中的第一人称代词,表示“我”的意思。它的主格和宾格形式都是I。例如: I am a student.(我是…

    2024年01月13日
    16