浅谈js作用域

每个JavaScript函数都是一个对象,对象中有属性,可以访问如:

        function text(){}
        console.log(text.name) // text

还有一些属性是我们访问不了的如:

        function text(){}
        console.log(text.[[scope]])  //报错

[[scope]]是函数的属性,但是是一种隐式的属性,我们访问不了,而他代表的就是函数产生的作用域,存储了执行期上下文的集合。它既然用不了,那它还有作用吗?有的虽然我们用不了,但是系统是可以使用的(只许州官放火不许百姓点灯)。

执行期上下文:当函数执行前,会创建一个执行期上下文的对象,执行期上下文定义了一个函数执行时的环境(我也不知道该怎么解释这句,就是这个函数会依赖这个环境去执行,,,大家试着去理解就可以),函数每次执行时对应的执行期上下文都是独一无二的,所以多次调用一个函数会产生多个执行期上下文,但是这么多执行期上下文放着也没用,还占内存,所以函数执行完毕以后就会销毁它自己产生的执行期上下文。

        function text(){}  //函数创建产生AO{}
        text();           // 函数执行 销毁AO对象,尽显渣男本色

作用域链: [[scope]]中所存的执行期上下文对象的集合,这个集合成链式链接,我们把这中链式链接叫做作用域链。
好了看天书环节过去了,可以看代码说问题了:

        var c = 10;
        function a(){  // 在a函数刚刚被定义的时候,它就有了自己的[[scope]]属性 里面第一位放着全局对象GO

            console.log(c) // 10  ,在AO里找不到c变量,就到GO里找到c 打印10

            function b(){ //在b函数刚刚被定义的时候,它就有了自己的[[scope]]属性 里面第一位放着a函数创建时的AO,第二位放着全局对象GO

                var b = 234;

            }

            var a = 123;

            b();//函数执行时在[[scope]]属性里面把自己创建的AO放在作用域链的顶端,AO和GO向下移一位。
        }
        var glob = 100;
        a();   //函数执行时在[[scope]]属性里面把自己创建的AO放在作用域链的顶端,GO向下移一位。
		a,b函数定义和执行时他们能访问到的作用域及访问先后顺序
         a 定义  a.[[scope]]  ---------------- 0 : GO
         
         a 执行  a.[[scope]]  ---------------- 0 : aAO
                                               1 : GO
                                               
         b 定义  b.[[scope]]  ---------------- 0 : aAO
                                               1 : Go
                                               
         b 执行  b.[[scope]]  ---------------- 0 : bAO
                                               1 : aAO
                                               2 : GO   

函数在执行时,会产生AO,当它访问变量时,先去找AO,再去找GO,这其实说明这样他们之间有一种联系,即作用域链。而自己创建的AO永远放在作用域链的顶端。
最后当b函数执行完毕,b函数销毁自己的AO对象,保留a函数的AO和全局的GO,处于定义阶段,等待执行,截止a函数也执行完毕时,a函数销毁自己的AO对象,保留全局GO对象,等待执行,但是注意一点,a函数的AO对象中,是有b函数的定义的,a函数的AO也保留在b函数的定义中,所以a函数的AO没有被真正意义上的销毁。

还有一点:a函数执行创建一个自己的AO,内部的b函数也可以访问这个AO,哪两个AO有什么关系呢?是复制了一个,还是大家用的同一个呢?看代码:

   function a() {
        var cc = 0;
        function b() {
            cc = 10;
        }
        b();
        console.log(cc) // 10 打印出了10,这说明b函数访问的AO对象和a函数创建的AO对象是同一个。
    }
    a();     

入职不久的小前端从今以后开始自己的技术分享之旅,欢迎建议和批评。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值