当前位置:网站首页>js中的作用域与作用域链
js中的作用域与作用域链
2022-04-23 05:56:00 【画不完的饼】
作用域与作用域链
首先先看一个例子:
let x = 1;
function A(y){
let x = 2;
function B(z){
console.log(x+y+z)
}
return B
}
let C = A(2);
C(3);
先来看以下,js底层代码执行的一个顺序:
ECstack = [ //执行栈
EC(G)={ //创建全局执行上下文
VO(G):{ //全局变量对象
... //包含全局对象原有的属性
x=1;
A=function(y){...} //创建函数的时候就确定了其作用域 (重点)
A[[scope]] = VO(G);
}
}
]
注:我们不管在哪一个执行上下文当中,除了创建变量或者堆以外,同时给当前的函数,声明了它所在的作用域是谁。
看上方例子,函数A在全局创建的,那么A的作用域就是全局的执行上下文。当A执行的时候,就会生成一个新的执行上下文(每个函数执行都会生成一个私有的执行上下文)。
此时,在A的执行上下文,我又创建了一个B函数。那么B也会生成一个私有的执行上下文,同时B的作用域也会被创建,那么B是在A的执行上下文创建的,那么B的函数作用域就是,当前这个A的执行上下文。
函数在执行上下文,除了获取arguments(实参对象),生成作用域外,还做了一件事,生成this指向
函数执行,有个执行主体,进来的第一件事情就是声明this指向,this指向后面说。
除此之外,它还初始化了它的链表,也就是我们常说的作用域链。作用域链的查找规则,就是上面加粗的文字。
下面总结一下:
函数的执行机制:
创建函数的时候:
(1)创建一个堆(存储代码字符串和对应的键值对)
(2)初始化了当前函数的作用域[[scope]]
作用域[[scope]]指的是所在上下文EC中的变量对象VO(变量对象)/AO(函数内的变量对象)
严格来说的话。作用域[[scope]] 与执行上下问是有区别的,作用域指的是当前上下问具体的存放变量的地方,上下文是既可以存变量,又能压缩代码放到执行栈执行的。但是,编程中,我们认为他们俩没啥区别,其实也是不会出错的。
函数执行的时候
创建一个新的执行上下文EC,并且压缩至栈(EC stack)里执行。
初始化this指向
初始化作用域链
创建AO变量对象存储变量
变量又会进行 arguments(它是函数运行时的实参对象) =》 形参 --》如果有变量提升,将变量提升,如果没有变量提升,会将代码执行。
下面看一下,上面题闭包的形成,以及作用域链的查找方式
重:
创建函数的时候,形成的是作用域,以及作用域是谁,函数执行的时候,一定会先初始化好它的作用域链,代码执行当中,遇到一个变量,首先看看它是不是私有变量,如果是,用自己的,如果不是,就会沿着作用域链,一级一级往上查找,一直查找到全局位置,找不到就会报错。这就是闭包,作用域链的一个查找过程。
版权声明
本文为[画不完的饼]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_39162041/article/details/105217720
边栏推荐
猜你喜欢
随机推荐
【ES6】 Promise相关(事件循环,宏/微任务,promise,await/await)
Log writing method (with time)
手动实现call,apply,bind函数
NodeJS 模块之间的使用
.Net Core 下使用 Quartz —— 【2】作业和触发器之初步了解作业
Set up a personal blog of jpress
条形码与二维码的生成
欢迎使用Markdown编辑器
Node accesses server-side static resources
Devexpress Gridview 添加全选列
.Net Core 下使用 Quartz —— 【3】作业和触发器之作业传参
SQLite compilation
Navicat 连接 oracle library is not loaded的解决方法
算数表达式
Analysis and setting of dead time
.Net Core 下使用 Quartz —— 【4】作业和触发器之作业属性和异常
ES6面试题(参考文档)
Aperçu de Redux
HDU-Tunnel Warfare
useCenterHook