关于作用域和作用域链的总结

Posted hauner

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于作用域和作用域链的总结相关的知识,希望对你有一定的参考价值。

 

今天听了一个同事(到现在了,还不知道人家的名字,怪不好意思的。。。捂脸。。不准笑我)的分享会,主要讲的就是作用域和作用域链,感觉受益匪浅。与我自己的理解相结合,感觉对这两个哥们了解的更多了。把我的心得总结如下,看不懂的别问我,因为我也不懂。看得懂的请感谢我和我的同事,因为下面的东西我们两个经验的总结。当然了主要还是感谢我这位同事,毕竟我是在他高大的肩膀上站了一会才有的下面的体会。好了书归正传,咱们拉回来说正事。

在说正事之前先介绍几个关键字:varletconstfunction

var:很久以前的东西了,反正是很久以前就有它了。不过我肯定比他大。那么他是干啥的嫩。定义变量,而且能作变量提升,所谓的变量提升就是。还是看代码吧。

console.log(a) //undefined

Var a=1

结果是undefined,没有报错,因为程序在执行前,只要是本作用域下用var声明的变量都会做个提升声明,但不会赋值。

 

Let:也是声明变量的,这个我知道,是es6新出炉的一个关键字。先让我骄傲一下。哈哈哈哈。那么他能不能做变量提升呢?答案是不能的,要是和var一样的话就不会再弄个let了。还有就是他有块作用域了,而var是函数作用域。还是看代码

console.loga //报错

Let a=1

这次的输出结果是报错,这就是所谓的不能变量提升了那么什么又是块作用域呢,代码,对还是代码

{

let a=1

Var b=2

}

Console.log(b) //2

Console.log(a) //报错

这就是块作用域,只要在块外边他就没有a这个变量,不管是块前还是块后,查无此人。

 

Const:这个家伙也是es6新出的,但是她是声明常量的。代码说话

const a=0

console.log(a) //0

a= 1 //报错    

Const同样是没有变量提升的,有块作用域,我就不代码演示了,同学们自己试去吧,毕竟纯手工打代码很累的。

 

Function:这位同志是声明函数用的,不皮了,代码

console.loga//function

a() //2

Function a(){console.log(2)}

同样的能够作提升,而且能够运行。不总结了,自己摸索去吧,其实我是不知道该怎么说了,毕竟水平比较低,共勉,勿笑。

 

值得一说的是还有一种无关键字声明变量,就是硬来,我也不说,直接干就是了。看下面的带码

function a(){

    b=10    

}

console.log(b)

//////////////////

function d(){

    c=10

}

d()

console.log(c)

///////////////////

console.log(ff)

ff=10

三段代码,自己试试,自己悟。

 

介绍完了这几位老弟,下面来说一下作用域,其实作用域在上边的介绍中也说得差不多了,要不还是直接说作用域链吧,太晚了,一会还要睡觉呢。

作用域链这个东西还是要先说js的作用域机制,是什么能?就是作用域内能访问作用域外的变量、常量、函数等,反之就不行了,作用域外不能访问作用域内的变量。(这就好比一个小黑屋安装一个双面镜,猥琐的某人在里边看的清清楚楚,外边的美女不知道还在那里换衣服照镜子呢,因为他看不见里边呀。)还是代码说话

let a=1

function b(){

     let c=2

     console.log(a)

     console.log(c)

}

b()  //1 //2

console.log(a) //1

console.log(c) //2

不多解释了自己悟吧!还是重点说作用域链吧。

 

先说一下作用域链的原理和实现机制,js要执行一段代码先在创建一个Global Scope(全局作用域),同事老师说了叫GO(Global Object),然后他就会看代码里都有什么,所有的var /function声明的先做个提升,全部挂载GO下边。函数内部的再说,然后就执行了。遇到var的时候赋值,当遇到letconst的声明的时候挂载并赋值。当遇到function的时候,编译function内部,然后创建一个AOActivation Object)他下边的所有声明挂载到AO下边,然后执行,再遇到function。。。。。。。。。。。。。。。。。。。。。。。。。。。。说不完的function太多了。用个代码加图看一下

 

let a = ‘a‘;

function b(){

    let ba=‘ba‘;

    bb = ‘bb‘;

    (function(){

        let ca=‘ca‘;

        cb=‘cb‘;

    })();

}

b()

 

先编译有了GO 然后又GO.a(属性) 和GO.b(方法)。然后执行遇到了GO.b又开始编译,又有了AO有了AO.ba(属性)和AO.nonamefn(方法),恩没看错没有AO.bb,只有GO.bb(属性)然后又执行匿名自执行函数,又有了一个AO就叫AO1吧号区分,然后又有了AO1.ca(属性)和GO.cb(属性)(不解释)

技术图片

 

  

今天就先弄到这里吧,毕竟坐车到家就九点了,孩子妈带孩子回娘家了,还要自己做饭,吃完饭都9点半了,现在我都找到一点网文工作者的感觉了,为了您们能够明天看到我的博文,我也是拼了,不能断更啊。不管写个好不好,各位亲们都要给掌声。就像德云社卢鑫玉浩说得一样,敬请诸位上仙天雷滚滚,帮小生顺利渡劫。

 

以上是关于关于作用域和作用域链的总结的主要内容,如果未能解决你的问题,请参考以下文章

前端:如何理解 JS 的作用域和作用域链?说说闭包的两个应用场景

对作用域和作用域链的理解

关于JS里的函数作用域链的总结

JavaScript中作用域和作用域链的简单理解(变量提升)

JavaScript中作用域和作用域链的简单理解(变量提升)

JavaScript面试题总结系列