Day14 - 词法作用域、块级作用域、作用域链、静态动态作用域

简介: Day14 - 词法作用域、块级作用域、作用域链、静态动态作用域

那些年听说的作用域



  • 全局作用域


  • 函数作用域


  • 块作用域


  • 词法作用域


  • 动态作用域


  • 全局作用域


  • 作用域链


作用域


作用域(英文:scope)是据名称来查找变量的一套规则,可以把作用域通俗理解为一个封闭的空间,这个空间是封闭的,不会对外部产生影响,外部空间不能访问内部空间,但是内部空间可以访问将其包裹在内的外部空间。


说白了就是一门语言如果声明的变量都放在全局,程序规模小还行如果规模一大肯定就不行了。所以就会采用各种方案来确定函数的作用域。


网络异常,图片无法展示
|


静态作用域与动态作用域


静态作用域(static scope) 与 词法作用域(lexical scope)


其实就是指的词法作用域,所谓静态作用域,也就是说在程序编译期通过对源代码的词法分析就可以确定某个标识符属于哪个作用域、作用域的嵌套关系(作用域链),在书写源代码时这些关系就已经确立了。


词法分析是编译中不可或缺的一环。


网络异常,图片无法展示
|


// 静态作用域:
var a = 10;
function fn() {
  var b = 1;
  console.log(a + b);
}
fn(); // 11


动态作用域(dynamic scope)


动态作用域是在运行时确定的,词法作用域关注函数在何处声明,而动态作用域关注函数从何处调用,其作用域链是基于运行时的调用栈的。


js语言中的变现为this 也就是上下文环境


function say() {
  debugger
  console.log('我的家乡:' + this.name)
}
var china = {
  name: '中国',
  say,
  beijing :{
    name: '北京',
    say
}
}
setInterval(() => Math.random() > 0.5 ? china.say() : china.beijing.say() , 1000)


因为 this 是指向的是函数运行时所在的环境,也就是说只有到了执行时才能确定。


扩展


其实动态与静态的问题在每种语言中都存在,


比如:


  • C++  动态联编与静态联编 - 虚函数


  • Java 动态编译与动态加载


函数作用域 与 块级作用域


下面我们细致的说一下函数作用域和块级作用域。


对于JS这种函数式语言,函数是一等公民,甚至有人想过用函数解决所有问题。


所以我们首先说说静态作用域的基础函数作用域。


函数作用域:指在函数内声明的所有变量在函数体内始终是可见的,可以在整个函数的范围内使用及复用。


var a = 'a'
function f1() {
    var b = 'b'
    function f2() {
        var c = 'c'
        function f3() {
          if(true) {
            var d = 'd'
          }
          console.log(a, b, c, d)
          debugger
        }
        f3()
    }
    f2()
}
f1()


作用域链


ECMA-262标准第三版定义,该内部属性包含了函数被创建的作用域中对象的集合,这个集合被称为函数的作用域链


网络异常,图片无法展示
|


块级作用域


块作用域是一个用来对之前的最小授权原则进行扩展的工具,将代码从在函数中隐藏信息扩展为在块中隐藏信息。


为了与其他主流语言靠近,块级作用域是ES6推出了let、const实现块级作用域。


var a = 'a'
function f1() {
    var b = 'b'
    function f2() {
        var c = 'c'
        function f3() {
          if(true) {
            debugger
            let d = 'd' // var 改为 let
          }
          debugger
          console.log(a, b, c, d)
        }
        f3()
    }
    f2()
}
f1()


上面只是将变量d改为使用let声明


网络异常,图片无法展示
|


但是运行结果就发生了变化


网络异常,图片无法展示
|


发生的原因就是使用var声明时,变量d的作用域在函数内。


而使用let声明时,作用域只在if代码块内。


面试攻略


  • 这道题其实是一个基础题,没有一个人不回答。回答的关键是在描述的系统性上面。比如你硬说词法作用域和动态作用域组成了JS的作用域体系就很奇怪。不在一个维度的描述会让人觉得描述不够系统和全面。


网络异常,图片无法展示
|


相关文章
|
1月前
|
JavaScript 前端开发
块级作用域和函数作用域有什么区别?
【10月更文挑战第29天】块级作用域和函数作用域在JavaScript中各有特点和用途。块级作用域提供了更精细的变量控制,有助于避免变量提升和意外的全局变量污染等问题;而函数作用域则在函数封装和模块化编程等方面有着重要的应用。在实际开发中,需要根据具体的需求和场景合理地选择使用哪种作用域来声明变量和组织代码。
|
1月前
|
存储 缓存 JavaScript
哪些情况适合使用块级作用域,哪些情况适合使用函数作用域?
【10月更文挑战第29天】块级作用域和函数作用域在不同的场景下各有优势,合理地选择和运用这两种作用域可以使JavaScript代码更加清晰、高效和易于维护。在实际开发中,需要根据具体的业务需求、代码结构和编程模式来决定使用哪种作用域,或者在适当的情况下结合使用两者,以达到最佳的编程效果。
|
1月前
|
JavaScript 前端开发 Java
块级作用域和函数作用域在执行效率上有什么不同?
【10月更文挑战第29天】块级作用域和函数作用域在执行效率上各有特点。块级作用域在变量查找速度、内存管理和闭包处理等方面具有一定的优势,尤其是在处理复杂的作用域嵌套和循环中的变量引用时,能够提供更高效和更准确的执行结果。然而,在实际应用中,由于现代JavaScript引擎的优化以及大多数场景下性能差异并不十分显著,因此不能简单地说哪种作用域的执行效率绝对更高,而是需要根据具体的代码逻辑、应用场景和性能需求来综合考虑和选择使用哪种作用域。
|
2月前
|
自然语言处理 JavaScript 前端开发
词法作用域和静态作用域有什么区别
【10月更文挑战第12天】词法作用域和静态作用域有什么区别
|
2月前
|
自然语言处理 JavaScript 前端开发
词法作用域
【10月更文挑战第12天】词法作用域
|
2月前
|
自然语言处理 JavaScript 前端开发
什么是词法作用域
【10月更文挑战第12天】什么是词法作用域
|
2月前
|
JavaScript 前端开发
作用域和作用域链及预解析
作用域和作用域链及预解析
26 4
|
7月前
|
JavaScript 前端开发
js开发:请解释什么是作用域(scope),并说明全局作用域、局部作用域和块级作用域的区别。
JavaScript中的作用域规定了变量和函数的可见性与生命周期。全局作用域适用于整个脚本,变量可通过全局对象访问,可能导致命名冲突和内存占用。局部作用域限于函数内部,每次调用创建新作用域,执行完毕后销毁。ES6引入的块级作用域通过`let`和`const`实现,变量仅在其代码块内有效,并有暂时性死区。作用域机制有助于代码组织和变量管理。
56 1
|
存储 JavaScript 前端开发
Javascript作用域 (局部作用域和全局作用域) 详细介绍
Javascript作用域 (局部作用域和全局作用域) 详细介绍
120 0
|
自然语言处理 前端开发 JavaScript
作用域闭包
作用域闭包
91 0