JavaScript——预编译 + 作用域链

一、预编译

1.js中函数运行的三个过程:(1)词法分析  (2)预编译   (3)运行代码

2.预编译过程:

        1.函数每次调用都会生成一个对象,叫做执行期上下文对象,也称为AO对象。

        2.给AO对象添加成员: 函数内部的局部变量和形参变量名作为AO对象的属性名。

        3.把传入的实参赋值给AO对象相对应的属性。

        4.局部函数声明,赋值  把局部变量的名字让AO对象也有一个一样的成员,把函数体赋值给这个属性。

例如:

            function fm(a) {
				console.log(a)
				var a = 20
				console.log(a)
			}
			fm(100)

 

分析:1.fm(100)调用函数时生成一个AO对象:AO:{ }

        2.将函数的形参和内部的变量以及函数作为AO的属性  AO:{ a:undefined}

        3.将传入的实参赋值给形参  AO: {a:100}

        4.函数执行,又重新给a赋值为20  AO:{a:20 }

  所以第一次打印100,第二次打印20

3.当全局作用域运行代码时 ,也有预编译

        1.生成一个对象Global Object  (GO对象)

        2.把所有的全局变量 设置为GO的属性名

        3.把所有的函数名作为GO的成员名,把函数体赋值给这个成员

        4.看是不是浏览器环境中的js脚本,如果是浏览器  还会执行一步: GO给window对象共享成员

 例如:

        

            console.log(a)
			var a = 20
			console.log(a)
			function fn() {
				console.log(123)
			}

分析:1.生成一个GO对象  GO:{ }

        2.把所有的全局变量 设置为GO的属性名  GO: { a;undefined }

        3.把所有的函数名作为GO的成员名,把函数体赋值给这个成员  GO :{a;undefined,function fn() {console.log(123)} }

        4.执行代码,第一个打印undefined,然后将a重新赋值为20,所以第二个打印20

二、作用域链

1.函数在定义/声明时, 就有了[[scopes]] 属性,也就是作用域"数组"(只能引擎使用), 里面保存了上层的AO对象。

2.函数调用时会生成AO对象  会把AO对象放在[[scopes]]中,并且每次调用都会放在scopes前面(顶部)

3.当函数中还嵌套了其他函数时,内部函数没有某个变量时,就会去它上一层AO对象中找,于是就会形成一条链,就称为作用域链

例如:

            function fn() {
				var a = 20
				function fm() {
					var b = 30
					console.log(a)
				}
				fm()
			}
			fn()

 

 当fm中没有找到a变量时,就会去fm的上一层AO对象中找,也就是到fn的[[scopes]]属性中找;所以最后打印a为20

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

z_小张同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值