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 前端开发 Python
函数与作用域
编程中的函数与作用域概念。函数是可重用的代码块,能提高代码的可读性、可维护性和复用性。基础用法包括定义、调用和返回值。高级用法涉及函数嵌套、匿名函数(lambda函数)和装饰器。装饰器能在不修改原函数代码的情况下添加功能。 作用域决定了变量的可见范围,从内到外是局部、嵌套、全局和内置作用域。闭包是能访问外部函数变量的内部函数,即使外部函数执行完毕,闭包仍能保留其状态。闭包常用于实现特殊功能,如记忆化和延迟执行。 立即执行函数表达式(IIFE)是JavaScript中的模式,用于创建私有作用域和防止变量污染全局。IIFE常用于封装变量、避免命名冲突以及实现模块化和函数作为参数传递。
|
1月前
|
JavaScript 前端开发
js开发:请解释什么是作用域(scope),并说明全局作用域、局部作用域和块级作用域的区别。
JavaScript中的作用域规定了变量和函数的可见性与生命周期。全局作用域适用于整个脚本,变量可通过全局对象访问,可能导致命名冲突和内存占用。局部作用域限于函数内部,每次调用创建新作用域,执行完毕后销毁。ES6引入的块级作用域通过`let`和`const`实现,变量仅在其代码块内有效,并有暂时性死区。作用域机制有助于代码组织和变量管理。
31 1
|
11月前
|
存储 JavaScript 前端开发
Javascript作用域 (局部作用域和全局作用域) 详细介绍
Javascript作用域 (局部作用域和全局作用域) 详细介绍
82 0
|
12月前
|
Linux 网络架构
暂时性死区以及函数作用域
暂时性死区以及函数作用域
126 0
|
设计模式 自然语言处理 JavaScript
一篇文章帮你真正理解javascsript作用域闭包
一篇文章帮你真正理解javascsript作用域闭包
67 0
|
自然语言处理 JavaScript 前端开发
词法作用域
词法作用域
69 0
词法作用域
|
自然语言处理 JavaScript 前端开发
作用域是什么
作用域是什么
90 0
|
存储 JavaScript 前端开发
深入理解作用域和闭包(上)
深入理解作用域和闭包(上)
深入理解作用域和闭包(上)
|
存储 缓存 JavaScript
深入理解作用域和闭包(下)
深入理解作用域和闭包(下)
深入理解作用域和闭包(下)
|
存储 自然语言处理 JavaScript
作用域相关的知识点:闭包、执行上下文、LHS/RHS、词法作用域
作用域相关的知识点:闭包、执行上下文、LHS/RHS、词法作用域
101 0