前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >java作用域-javaScript预编译、作用域,作用域链详解

java作用域-javaScript预编译、作用域,作用域链详解

作者头像
宜轩
发布于 2022-12-29 03:21:30
发布于 2022-12-29 03:21:30
1.4K00
代码可运行
举报
文章被收录于专栏:囍楽云博客囍楽云博客
运行总次数:0
代码可运行

ES5中只分为全局作用域和函数作用域java作用域,也就是说for,if,while等语句是不会创建作用域的。ES6(let,const)除外。

  几个概念

  执行环境:也称为执行期上下文,当函数执行时,会创建一个称为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,执行上下文被销毁。它定义了变量或函数有权访问的其他数据,决定了它们的各自行为。

  执行环境分为全局执行环境和函数执行环境(这个名字我自己取的),其中在浏览器中全局执行环境是一个对象。

  活动对象(AO)与变量对象(OV): 活动对象也就是前面说的执行期上下文的内部对象,每个函数执行的时候都会创建这样一个活动对象,当函数函数还未执行完毕的时候,又进入到其他的作用域中,那么这个活动对象就变为变量对象(OV),比如说在一个函数里面执行另一个函数,另一个函数会创建一个活动对象,而当前的变为变量对象。当另一个函数执行完毕,它的执行上下文被销毁,返回上一个函数,那么上一个函数的变量对象又变为活动对象。可以理解为当前执行环境的执行期上下文的内部对象称为活动对象,否者称为变量对象。另外变量对象和活动对象都存储了本级环境中所定义的变量和函数,函数的话还包括参数

预编译:在进入全局环境和函数环境之前就会进行

  预编译步骤:

  1、创建AO对象(活动对象 或者说执行期上下文) 如果是全局环境就叫做window对象或者Go对象

  2、查找形参和变量声明,值为

  3、将实参和形参相统一,值为实参里面的值值为实参里面的值

  4、找函数声明,属性值为声明时候的属性值

  [scope]:每个函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供引擎存取,[scope]就是其中一个。[scope]指的就是我们所说的作用域,其中存储了前面说的执行期上下文的集合,这个属性是在函数被定义的时候就创建

  作用域链:[scope]中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。

  寻找变量的过程就是从变量作用域链开始查找的,如果在当前的变量作用域没找到,那么就去上一个变量作用域里面去早

  作用域链创建的过程:

  预编译

  先来理解一下预编译,看例子:

   var a = 10

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
            b = 20
            function test (a, b) {
                console.log(a, b, test1, d)
                var a = 10
                console.log(a)
                if (b) {
                    var c = 20
                }
                console.log(a, b, test1, d)
                function test1 () {
                    
                }
                var d = function () {
                    
                }
                console.log(a, b, test1, d)
            }

  第一步 全局环境下预编译

  进入全局环境并在执行全局环境代码之前进行预编译,跟着我前面说步骤

  1、生成GO对象

  GO: {}

  2、查找形参和变量声明(这里不是函数,因此没有查找形参这一步),值为

  GO: { a: } // 注意这里因为b是没有声明的所以不会被放到GO这个活动对象里面

  3、将实参和形参相统一,值为实参里面的值值为实参里面的值(在全局环境依然没有这一步)

  4、找函数声明,属性值为声明时候的属性值

  GO: { a: , test: () {} }

  第二步 全局环境下执行代码

  先执行 a = 10 ,注意因为声明的步骤我们已经在预编译的时候执行过了,所以这里就只是赋值操作,此时的GO对象是

  GO: { a: 10, test: () {} }

  再执行 b = 10 ,注意这里由于没有声明预编译的时候没有被放到GO对象里面去,因此在这行代码之前访问这个对象会报错,当执行到这个代码的时候会被放到GO对象里面去,此时的GO对象为

  GO: { a: 10, test: () {} , b: 10}

  第三步 函数环境下预编译

  现在该执行test函数了,进入到一个新的执行环境 ,在执行函数代码之前会进行预编译

  1、生成AO对象

  AO: {}

  2、查找形参和变量声明, 值为

  AO: { a: , b: , c: , d: }

  3、将实参和形参相统一,值为实参里面的值

  AO: { a: 1, b: , c: , d: }

  4、找函数声明,属性值为声明时候的属性值

  AO: { a: 1, b: , c: , d: , test1: () {} }

  第四步 函数环境下执行代码

  依旧和在全局环境下执行代码一样,执行赋值语句,下面就说当执行到某个.log() 的时候它的AO对象是什么

  第一个.log()的时候AO对象为

  AO: { a: 1, b: , c: , d: , test1: () {} }

  第二个.log()的时候AO对象为

  AO: { a: 10, b: , c: , d: , test1: () {} }

  第三个.log()的时候AO对象为

  AO: { a: 10, b: , c: , d: , test1: () {} }

  第三个.log()的时候AO对象为

  AO: { a: 10, b: , c: , d: () {}, f: () {} }

  注意: 在预编译的时候,像let和const这种块级作用域的,如果放到if语句里面,是不会被添加到AO或者GO对象里面的,像上面的例子中if里面如果换成let或者const的话,预编译阶段是不会被添加进去的

  作用域链

  看例子:

  第一步:a函数被定义,创建[scope]

  上面函数被定义的时候,[scope]会把当前函数所在的上下文放入这个对象中。需要注意的时候,函数存储被定义时的上下文的时候java作用域,只是存储的是一个引用,而不是副本,正是因为这样,才能形成作用域链,当函数在本函数的AO对象找不到的时候,就沿着本函数的[scope]存储的上一个作用域的变量对象的引用到上一个作用域里面去早。

  第二步,执行函数

  执行函数的时候,会先发生预编译,然后会把AO对象放入到这个[scope]中

  第三步:函数b在函数中是被定义了的,在执行预编译的时候,会为它创建一个[scope]属性,里面存储了b函数当前所在的上下文,也就是a的[scope]。

  第四步,执行b函数

  和a函数执行一样,依然创建一个AO对象放入

  作用域链就是这样形成的,每个函数都有一个[scope]里面储存了运行期上下文的集合。寻寻找变量的过程,就是沿着作用域链从上到下寻找,找不到就在最上面一层定义,也就是在global object里面成为全局变量,也就是我们常说的变量不定义就使用会成为全局变量。

  ---------------------

本文共 1709 个字数,平均阅读时长 ≈ 5分钟

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
JavaScript——执行环境、变量对象、作用域链
这几天在看《javascript高级程序设计》,看到执行环境和作用域链的时候,就有些模糊了。书中还是讲的不够具体。通过上网查资料,特来总结,以备回顾和修正。
喝茶去
2019/04/16
7890
JavaScript作用域及作用域链
作用域 作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。 JavaScript 采用词法作用域(lexical scoping),也就是静态作用域。 因为 JavaScript 采用的是词法作用域,函数的作用域在函数定义的时候就决定了。 而与词法作用域相对的是动态作用域,函数的作用域是在函数调用的时候才决定的。
青梅煮码
2023/03/02
1.5K0
转 javascript基础详解-执行环境与作用域链
函数调用都有与之相关的作用域和上下文。从根本上说,范围是基于函数(function-based)而上下文是基于对象(object-based)。换句话说,作用域是和每次函数调用时变量的访问有关,并且每次调用都是独立的。上下文总是关键字 this 的值,是调用当前可执行代码的对象的引用。
用户2458785
2018/08/28
4120
作用域链和原型链的区别_原型链和作用域链
题外话:最近面试一直被问到作用域链的问题,所以还是要深入透彻的学习一下这两个概念。
全栈程序员站长
2022/11/16
4580
作用域链和原型链的区别_原型链和作用域链
前端入门18-JavaScript进阶之作用域链声明正文-作用域链
作为一个前端小白,入门跟着这几个来源学习,感谢作者的分享,在其基础上,通过自己的理解,梳理出的知识点,或许有遗漏,或许有些理解是错误的,如有发现,欢迎指点下。
请叫我大苏
2018/12/24
4420
JS入门难点解析8-作用域,作用域链,执行上下文,执行上下文栈等分析
(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)
love丁酥酥
2018/08/27
6930
JS入门难点解析6-作用域链
(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)
love丁酥酥
2018/08/27
6790
JavaScript的预编译过程
在全局环境中会生成一个 GO对象 (Global Object),还是按照上面的四步执行。
FinGet
2019/06/28
4060
JavaScript的预编译过程
详解作用域链
在本文中,我们将着重讨论作用域链。首先我们会了解作用域、块级作用域、相关的一些重要概念等前置基础知识,接着我们会通过几个例子来对作用域链进行详细讲解,最后我们还会涉及作用域链延长的问题。在了解完上述知识之后,在本文主要内容的最后,我们还精选了网上几个作用域链相关的题目供小伙伴思考。
石璞东
2020/05/22
5680
JavaScript 作用域和作用域链
作用域就是变量与函数的可访问范围。在JavaScript中,变量的作用域有全局作用域和局部作用域两种。
零式的天空
2022/03/02
1.7K0
JavaScript闭包的深入理解
闭包算是javascript中一个比较难理解的概念,想要深入理解闭包的原理,首先需要搞清楚其他几个概念: 一、栈内存和堆内存 学过C/C++的同学可能知道,计算机系统将内存分为栈和堆两部分(大学的基础课,忘掉的赶紧重新捡起来)。 栈内存(连续的存储空间,类似数据结构中的栈):主要用来存放数值、字符、内存地址等小数据 堆内存(散列的存储空间,类似数据结构中的链表):存放可以动态变化的大数据 二、基本类型和引用类型 JavaScript将变量分为两种类型: 基本类型:Number、String、Boolean
小古哥
2018/03/08
1.3K0
JavaScript闭包的深入理解
深入理解变量对象、作用域链和闭包
执行上下文、执行栈、作用域链、闭包,这其实是一整套相关的东西,之前转载的文章也有讲到这些。下面两篇文章会更加详细地解释这些概念。
Chor
2019/11/07
7380
【JS】预编译详解
函数dmeo为经声明就可正常调用,执行函数demo时,先将1赋值给b,再将b的值赋值给a;虽然a、b是在函数作用域中,但由于b未经声明,所以下面在browser环境中输出的结果表明b 在 window 属性中,而 a 则不会出现在全局对象中;函数demo的声明是在全局作用域,所以它归window对象所有
好吃懒洋洋
2022/11/15
1.3K0
【JS】预编译详解
由 JavaScript 的 with 引发的探索
1. 背景 某天吃饭的时候突然想到,都说 with 会有问题,那么是什么问题,是怎样导致的呢?知其然不知其所以然,在好奇心的驱使下,从 with 出发,一路追溯到 VO、AO。那么先来复习一下 with 是干嘛的吧。 2. with js 的 with 是为对象访问提供命名空间式的访问方式,with 创建一个对象的命名空间,在这个命名空间内你可以直接访问对象的属性,而不需要通过对象来访问: const o = { a: 1, b: 2 }; with (o) { console.log(a); /
用户1097444
2022/06/29
3170
由 JavaScript 的 with 引发的探索
理解javascript作用域和作用域链
作用域就是变量和函数的可访问范围,控制着变量和函数的可见性与生命周期,在JavaScript中变量的作用域有全局作用域和局部作用域。
令仔很忙
2018/09/14
2.2K0
理解javascript作用域和作用域链
JS学习系列 06 - 变量对象
上一节我们讨论了执行上下文,那么在上下文中到底有什么内容,为什么它会和作用域链扯上关系,JS 解释器又是怎么找到我们声明的函数和变量,看完这一节,相信大家就不会再迷惑了。
leocoder
2018/10/31
1.3K0
作用域及作用域链的解释说明
javascript中作用域是指变量与函数可访问的范围。作用域分为两类,一种是全局作用域,一种是局部作用域。全局变量拥有全局作用域,在JavaScript代码中的任何地方都有定义。局部变量是在函数体内声明而且只作用在函数体内部以及该函数体的子函数的变量。下面我们对全局作用域和局部作用域来做一个深入的理解。
OECOM
2020/07/02
1.2K0
作用域及作用域链的解释说明
从 JavaScript 作用域说开去
在电脑程序设计中,作用域(scope,或译作有效范围)是名字(name)与实体(entity)的绑定(binding)保持有效的那部分计算机程序。不同的编程语言可能有不同的作用域和名字解析。而同一语言内也可能存在多种作用域,随实体的类型变化而不同。作用域类别影响变量的绑定方式,根据语言使用静态作用域还是动态作用域变量的取值可能会有不同的结果。
一缕殇流化隐半边冰霜
2018/08/29
8730
从 JavaScript 作用域说开去
前端学习(35)~js学习(十二):预编译
规律1:任何变量,如果未经声明就赋值,此变量是属于 window 的属性,而且不会做变量提升。(注意,无论在哪个作用域内赋值)
Vincent-yuan
2020/03/18
4640
JS底层运行机制
众所周知,计算机是有内存的,计算机会在内存中开辟一块空间去供js执行,这个空间我们称之为执行栈
子夜星辰
2022/11/15
1.9K0
相关推荐
JavaScript——执行环境、变量对象、作用域链
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文