javascript从范围链讨论闭包
神马是封闭的概念,意思是女人是理性的。
闭包是指一个函数可以访问另一个函数范围内的变量。这个概念有点混乱,分了吧。从概念上讲,闭包有两个特征:
1.功能2。访问另一个函数作用域中的变量。在ES 6之前,Javascript只有函数作用域的概念,没有块级作用域的概念(但是catch捕获的异常只能在catch块中访问)(IIFE可以创建局部作用域)。每个函数作用域都是封闭的,也就是说,不能从外部访问函数作用域中的变量。
Getname () {var name=' beauty的名字';console.log(名称);//'美女的名字' }功能显示名称(){ console . log(name);//报错}但为了得到美女的名字,从未放弃的王将代码改为:
Getname () {var name=' beauty的名字';函数display name(){ console . log(name);}返回displayName} var beauty=getName();美女()//《美女的名字》现在,美女是一个封闭的袋子,单身的王粲想玩多少就玩多少。(但不建议单王用中文写变量名,不要学。).
关于闭包还有三点:1。闭包可以访问当前函数以外的变量。
函数getOuter(){ var date=' 815 ';函数GetDate(str){ console . log(str date);//访问外部日期}返回getDate('今天是:');//'今天是:815 ' } getOuter();GetDate是一个闭包。这个函数执行时会形成一个作用域A,变量日期在A中没有定义,但是可以在父作用域中找到这个变量的定义。
2.即使外部函数已经返回,闭包仍然可以访问外部函数定义的变量。
函数getOuter(){ var date=' 815 ';函数GetDate(str){ console . log(str date);//访问外部日期}返回getDate//外部函数返回} var today=getOuter();Today ('Today是:');//‘今天是815’今天(‘明天不是’);//‘明天不是:815’3。闭包可以更新外部变量值。
函数updateCount(){ var count=0;函数getCount(val){ count=val;console.log(计数);}返回getCount//外部函数返回} var count=updateCount();计数(815);//815 count(816);//816如果作用域链是粗闭包,你能访问外部函数的变量吗?这是关于Javascript中的范围链。Javascript中有一个执行上下文的概念,它定义了变量或函数可以访问的其他数据,并决定了它们各自的行为。每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都存储在这个对象中。你可以把它想象成一个普通的Javascript对象,但是只能修改它的属性,不能引用它。
变量也有父作用域。当访问一个变量时,解释器将首先在当前范围内寻找标记,如果没有找到,它将转到父范围,直到找到该变量的标记或者父范围不再存在。这是范围链。
范围链类似于原型继承,但有一点不同:如果找普通对象的属性,会返回undefined如果在当前对象或其原型中找不到它;但是,如果搜索到的属性在范围链中不存在,将引发ReferenceError。
范围链的顶端是一个全局对象。对于全局环境中的代码,范围链只包含一个元素:全局对象。因此,当变量在全局环境中定义时,它们将在全局对象中定义。调用函数时,作用域链包含多个作用域对象。
全局环境多讲了一点范围链(红皮书中有关于范围和执行环境的详细解释)。让我们举一个简单的例子:
//my _ script . js ' use strict ';var foo=1;var bar=2;在全局环境中,创建了两个简单的变量。如前所述,此时变量对象是一个全局对象。
非嵌套函数更改代码以创建没有函数嵌套的函数:
使用“严格”;var foo=1;var bar=2;function my func(){///-定义局部到函数变量var a=1;var b=2;var foo=3;console.log('在myFunc内部');} console . log(' outer ');///-然后,调用it : myfunc();当定义myFunc时,myFunc的标识符被添加到当前作用域对象(在本例中是全局对象),并且该标识符引用一个函数对象。函数对象包含函数的源代码和其他属性。我们关心的属性之一是内部属性[[作用域]]。[[scope]]引用当前的scope对象。也就是说,当创建函数的标识符时,我们可以直接访问作用域对象(在本例中是全局对象)。
更重要的是,myFunc引用的函数对象不仅包含函数的代码,还包含指向创建时间的作用域对象。
调用myFunc函数时,会创建一个新的作用域对象。的新作用域对象包含由myFunc函数及其参数定义的局部变量。这个新作用域对象的父作用域对象是我们在运行myFunc时可以直接访问的作用域对象。
嵌套函数如前所述,当函数返回未被引用时,它将被垃圾收集器回收。但是对于闭包(函数嵌套是形成闭包的一种简单方式),即使外部函数返回,函数对象在创建时仍然会引用作用域对象。
使用“严格”;函数create counter(initial){ var counter=initial;函数增量(值){ counter=value}函数get(){ return counter;}返回{ increment: increment,get : get };} var my counter=create counter(100);console . log(my counter . get());//返回100 mycounter . increment(5);console . log(my counter . get());//返回105当调用createCounter(100)时,嵌入函数递增,get都有对createCounter(100)作用域的引用。如果createCounter(100)没有返回值,那么createCounter(100)的作用域就不再被引用,所以可以进行垃圾收集。但是,因为createCounter(100)实际上有一个返回值,并且返回值存储在myCounter中,所以对象之间的引用关系会发生变化。
这需要一些时间来思考:即使createCounter(100)已经返回,它的作用域仍然存在,并且只能由内联函数访问。您可以通过调用myCounter.increment()或myCounter.get()直接访问createCounter(100)的范围。
调用myCounter.increment()或myCounter.get()时,会创建一个新的作用域对象,这个作用域对象的父作用域对象将是目前可以直接访问的作用域对象。
执行时返回计数器;在get()所在的作用域中找不到对应的标识符,所以将在作用域链中向上搜索,直到找到变量计数器,然后返回。调用增量(5)会更有趣。当单独调用增量(5)时,参数值将存储在当前范围对象中。要访问值,函数可以立即找到当前范围内的变量。然而,当函数试图访问计数器时,没有找到它,所以它在范围链中向上搜索,并在createCounter(100)的范围中找到相应的标记,增量()将修改计数器的值。此外,没有其他方法可以修改此变量。这也是闭包的力量,它可以存储私有数据。
相似的函数对象,不同的作用域对象对于上面的反例,我们来谈谈扩展。看看代码:
//MySQL . js ' use strict ';函数createCounter(初始){ /*.参见前面示例中的代码.*/}///-create counter objects var my counter 1=create counter(100);var my counter 2=create counter(200);创建myCounter1和myCounter2后,关系图非常紫:
在上例中,myCounter1.increment和myCounter2.increment的函数对象具有相同的代码和相同的属性值(名称、长度等)。),但是它们的[[作用域]]指向不同的作用域对象。
这有以下结果:
风险值a,b;a=my counter 1 . get();//a等于100 b=my counter 2 . get();//b等于200 mycounter 1 . increment(1);my counter 1 . increment(2);my counter 2 . increment(5);a=my counter 1 . get();//a等于103 b=my counter 2 . get();//b一个等于205的作用域,这个作用域将存储变量,但这不是作用域的一部分,它取决于函数是如何被调用的。关于这一点的总结,你可以阅读这篇文章:JavaScript面试问题:事件委托和这个。
版权声明:javascript从范围链讨论闭包是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。