重温js——作用域和作用域链

简介: js代码执行,会在call stack创建对应的作用域(执行上下文),然后每一个上下文中会有一个VO来保存当前作用域的变量. 但是VO中如果会创建函数,那么函数中有一个额外的属[[scoped]]会指向栈中最顶层的VO(AO);

作用域


看过上一篇重温js——执行上下文,里面提到了一个概念叫做执行环境,在里面说到了 全局环境,函数环境和eval的环境。那里面所说的环境,其实就是作用域,所以这里在稍微唠叨一下,作用域有以下:


  • 全局作用域(Global scope):和前文的GO对象一样
  • 函数作用域(Function scope):处于每一次执行的VO对象
  • 块级作用域(es6以后补充的):es6以后定义变量的关键字变成let和const, let 和 const有自己的规则,详情查看.


既然变量有作用域,函数也有作用域,那么他们是怎么连接起来形成作用域链呢?


作用域链


js代码执行,会在call stack创建对应的作用域(执行上下文),然后每一个上下文中会有一个VO来保存当前作用域的变量. 但是VO中如果会创建函数,那么函数中有一个额外的属[[scoped]]会指向栈中最顶层的VO(AO);


上面的那一段话有点不好理解,咋们来举个例子,画个图来看看就明白了。


// 这一道题目输出的a是多少
var a = 1;
function A(){
  console.log(a)
}
function B(){
 var a = 123;
 var C = A;
 C();
}
B();


需要理解这个例子,咋们来画画图。


7c995673a5d9434aa9019ae767b1fa12.gif


上面图中的每一帧可以理解为代码在运行过程中所作的事情。


咋们先那函数C 来分析,函数C 指向的是函数A的地址,然而函数A又是在全局的作用域中创建的,所以函数A的[[scoped]] 是指向GO对象的. 如下图红色线条:


eba859f29b0240fa882fd15e961f1076.png


C 中的变量查找方式C ---> A ---> GO, 形如: C ---> A ---> GO这样作用域指向的形式,我们称之为作用域链。查找对象也是严格按照作用域链来查找的。


结果:


5a5cabba00f64586ad900dfb583be757.png


闭包


在上面的那个例子中,我们的函数A相当于保存到了函数B的内部(B内部使用的是引用地址),实际上函数A所处的作用域还是全局作用域。


  • 从广义上来说,函数内部使用函数,并且里面函数用到了外面的作用的变量。上面例子中的函数B就形成了闭包。


  • 从狭义上来讲:函数内部使用了外部的变量,并且函数在其他作用域调用就形成闭包。


// 这一道题目输出的a是多少
var a = 1;
function A(){
  console.log(a)
}
function B(){
 var a = 123;
 var C = A;
 C();
}
B();


其实闭包在我们的开发中是非常常见的。其实还有一个问题,就是说闭包带来的问题:

内存泄漏, 这个观点是不对的。内存泄漏是指内存中的变量不能够访问并且不能被垃圾回收给清理掉。上面的那个例子中变量a可以找到吧。我们找到他的方式有很多种。


这里有的人可能需要说,我们看到的闭包是下面的这种形式?


function A(){
 var a = 1223;
 return function(){
    console.log(a)
  }
}
var afunc = A();
afunc();


上面的代码,先创建函数A,然后执行函数A,然后函数A返回一个函数。只要函数执行了,call stack 中会清空哇,哪里会有内存占用不释放呢?

相关文章
|
24天前
|
JavaScript 前端开发
js的作用域作用域链
【10月更文挑战第29天】理解JavaScript的作用域和作用域链对于正确理解变量的访问和生命周期、避免变量命名冲突以及编写高质量的JavaScript代码都具有重要意义。在实际开发中,需要合理地利用作用域和作用域链来组织代码结构,提高代码的可读性和可维护性。
|
24天前
|
自然语言处理 JavaScript 前端开发
[JS]作用域的“生产者”——词法作用域
本文介绍了JavaScript中的作用域模型与作用域,包括词法作用域和动态作用域的区别,以及全局作用域、函数作用域和块级作用域的特点。通过具体示例详细解析了变量提升、块级作用域中的暂时性死区等问题,并探讨了如何在循环中使用`var`和`let`的不同效果。最后,介绍了两种可以“欺骗”词法作用域的方法:`eval(str)`和`with(obj)`。文章结合了多位博主的总结,帮助读者更快速、便捷地掌握这些知识点。
30 2
[JS]作用域的“生产者”——词法作用域
|
4月前
|
JavaScript 前端开发
浅谈js作用域
浅谈js作用域
34 0
|
25天前
|
前端开发 JavaScript 数据处理
CSS 变量的作用域和 JavaScript 变量的作用域有什么不同?
【10月更文挑战第28天】CSS变量和JavaScript变量虽然都有各自的作用域概念,但由于它们所属的语言和应用场景不同,其作用域的定义、范围、覆盖规则以及与其他语言特性的交互方式等方面都存在明显的差异。理解这些差异有助于更好地在Web开发中分别运用它们来实现预期的页面效果和功能逻辑。
|
24天前
|
JavaScript 前端开发
如何在 JavaScript 中实现块级作用域?
【10月更文挑战第29天】通过使用 `let`、`const` 关键字、立即执行函数表达式以及模块模式等方法,可以在JavaScript中有效地实现块级作用域,更好地控制变量的生命周期和访问权限,提高代码的可维护性和可读性。
|
1月前
|
JavaScript 前端开发
javascript的作用域
【10月更文挑战第19天javascript的作用域
|
2月前
|
JavaScript 前端开发
JavaScript 作用域
JavaScript 作用域是指程序中可访问的变量、对象和函数的集合。它分为函数作用域和局部作用域。函数作用域内的变量仅在函数内部可见,而全局作用域的变量在整个网页中均可访问。局部变量在函数执行完毕后会被销毁,而全局变量则在整个脚本生命周期中都存在。未使用 `var` 关键字声明的变量默认为全局变量。
|
2月前
|
JavaScript 前端开发
js作用域
js作用域
16 1
|
3月前
|
JavaScript 前端开发
js 变量作用域与解构赋值| 22
js 变量作用域与解构赋值| 22
|
3月前
|
JavaScript 前端开发
JavaScript基础知识-作用域(action scope)
关于JavaScript基础知识中作用域的介绍。
41 1
JavaScript基础知识-作用域(action scope)