深入理解js的作用域

全局作用域

  • 全局作用域在页面打开时创建,页面关闭时销毁
  • 全局作用域的顶级对象是window,由浏览器创建
  • 全局作用域中声明的变量、函数都是window的对象

函数作用域

  • 函数作用域在函数被调用时创建,在函数执行完毕后销毁
  • 每次调用函数,都会创建一个新的作用域,它们之间是相互独立
  • 全局作用域的变量可以在函数作用域中访问,反之不行
  • 在函数作用域中访问变量时,如果作用域内有,访问,如果没有,就去上一层作用域访问,一直到全局作用域,还是没有,就是未定义undefined

深入理解作用域

执行期的上下文

  • 当函数代码执行的前期,会创建一个执行期上下文内部对象AO
  • 这个内部对象是预编译的时候创建的,函数被调用时会先进行预编译
  • 全局代码执行的前期也会创建一个执行期的上下文对象GO

函数作用域的预编译

  • 首先,创建AO对象 AO{}
  • 接着,找形参和变量声明,将变量和形参名当作AO对象的属性名,值为undefined
  • 实参形参相统一
  • 在函数体里找函数声明,值赋为函数体

全局作用域的预编译

  • 创建GO对象
  • 找变量声明,将变量名作为GO对象的属性名,值为undefined
  • 找函数声明,值赋为函数体
function fn(a,c){
            console.log(a)//function a(){}
            var a=123
            console.log(a)//123
            console.log(c)//function c(){}
            function a(){}
            if(false){
                var d=678
            }
            console.log(d)//undefined
            console.log(b)//undefined
            var b=function(){}
            console.log(b)//function(){}
            function c(){}
            console.log(c)//function c(){}
        }
        fn(1,2)

分析一下上述代码:

预编译阶段:

  • 函数体中的形参为a,c,变量有a,b,c,d。这几个的值一开始都是undefined—将变量和形参名当作AO对象的属性名,值为undefined
  • 函数调用,a=1,c=2—实参形参相统一
  • a再从1改为function a(){},c从2改为function c(){}—找函数声明,值赋为函数体
    到此,预编译结束

继续分析:

  • 调用函数时,函数体内的第一句是打印a,此时a的值为function a(){}
  • 第二句var a=123,console.log(a)//123
  • console.log©,与第一句情况一样,此时c值为function c(){}
  • function a(){} a值又变成了函数体
  • if(false)虽然if条件为假,并不执行,但是预编译时,仍然会对d进行声明,只是不会赋值,所以后边console.log(d)//undefined
  • 接着 console.log(b),由于js存在声明提前,所以先有var b,然后打印是undefined,最后再给b赋值为函数体(var b=function(){}这句不是函数声明,而是定义b)
  • 最后打印c,c值仍为函数体
    再来看一段代码:
        var global
        function fa() {
            function fb() {
                var bb = 123
                aa = 0
                console.log(bb)//123
                console.log(aa)//0
            }
            console.log(aa)//undefined
            var aa = 234
            console.log(aa)//234
            fb()
            console.log(aa)//0
            console.log(global)//undefined
        }
        fa()

再来理解一下,函数作用域是在函数被调用的时候创建的,fb函数也是在fa函数调用的时候才被定义的。
另外这里存在闭包的概念,aa = 0这句并不是全局定义,fb能够访问fa中的变量,而fa是有对aa的声明的。

总结:先分析预编译阶段,之后分析执行阶段,注意声明提前,只提前了变量和函数的声明,赋值不提前。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值