JavaScript变量对象、执行环境和作用域链

    xiaoxiao2021-03-25  122

    首先不管是变量对象、执行环境或作用域链都是内部对象你无法直接用js访问。

    JS两种变量类型的访问和内存问题

    基本数据类型是按值访问的

    引用类型的值是保存在内存中的对象。JS不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。 操作对象的时候实质是操作对象的引用而不是实际的对象。 严谨地说:

    var a={v:2,c:3}; var b=a //这种情况操作的是引用 a.x=23; //这种情况操作的是对象,实际也是找到这个对象并给这个对象的属性赋值 //这个属性是一个基本数据类型,那么赋值是按值访问的

    动态的属性

    对于引用类型,可以添加属性和方法,也可以删除改变属性和方法。 但是基本类型不能,尽管不会报错:

    var name="xx"; name.age=27; console.log(name.age); //undefiend

    复制变量值

    从一个变量向另一个变量复制基本类型值时,会在变量对象上创建一个新值,然后把该子复制到为新变量分配的位置上 。

    从一个变量向另一个变量复制引用类型的值时,同样会将存储在变量对象中的值复制一份放到新变量分配的空间中。 不同的是,这个值的副本实际是一个指针! 这个指针指向存储在堆中的一个对象。 复制操作结束后,两个变量实际上将引用同一个对象。因此改变其中一个变量就会影响另一个变量!

    这个图描述了 保存在变量对象中的变量和保存在堆中的对象之间的关系

    详解介绍变量对象

    JavaScript中的执行环境包括全局执行环境和函数执行环境这两种,每进入到一个执行环境都会创建一个变量对象,这个对象中记录了在当前执行环境中可以访问到的变量,它们以变量对象的属性形式存在。也就是说这个变量对象成为“作用域”这个抽象概念的实体。

    变量对象 浏览器的解析器在处理数据时会在后台使用它,无法通过代码访问。

    全局环境中: 1) 先是函数声明 2)变量声明其值为undefined,一直执行到这条语句的时候才被赋予具体值 函数环境中: (进入函数环境时,变量对象进行以下初始化) 1)arguments对象,对象中的值被赋予具体的参数值 2)函数的形参,变量对象的一个属性,其属性名就是形参的名字,其值对应实参的值,不传递的就是undefined 3)函数声明:也是变量对象的一个属性,属性名和值都是函数对象创建出来的,值为指向某个函数对象的引用 4) 变量声明:变量对象的一个属性,属性名为变量名

    总结一句话:在进入上下文的时候(比如进入到一个全局环境或者是调用某个函数),变量对象除了arguments,函数的声明,以及参数被赋予了具体的属性值,其它的变量属性默认的都是undefined。

    执行环境(上下文)和变量对象

    执行环境定义了变量或函数有权访问的其他数据。每个执行环境都有一个与它关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。

    全局执行环境 web浏览器中,全局执行环境被认为是window对象,因此所有全局变量和函数都是作为window的属性存在。

    函数执行环境 每个函数都有自己的执行环境。 当执行流进入一个函数时,函数的环境会被推入一个环境栈中。 而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。

    执行环境的销毁 某个执行环境中的所有代码执行完毕后,该环境被销毁。里面的变量和函数定义也被销毁! 对于全局执行环境来说就是程序退出,如关闭网页或浏览器。

    创建作用域链

    作用域链 — [[Scope]]引用,这是一个函数的内部属性。 它本质是一个指针列表,存放了它能够访问的各个执行环境的变量对象的引用!

    (当代码在一个环境中执行时,就会创建变量对象的一个作用域链scope chain。 )

    作用域的用途: 保证对执行环境有权访问的所有变量和函数的有序访问。 作用域链的前端始终是当前执行的代码所在的变量对象。 如果这个环境是函数,则将其活动对象作为变量对象。 活动对象在最开始时只包含一个变量,即argument对象。作用域链中的下一个变量对象来自包含环境,而再下一个变量对象来自下一个包含环境。 以此类推。。。

    作用域链与标识符搜索

    标识符的搜索,也是沿着作用域链一级一级的搜索,搜索过程始终从作用域链的前端开始,逐级向后回溯。

    作用域链:

    内部执行环境可以通过作用域链访问外部执行环境中的变量或函数,反之无效。 这些环境之间是线性,有次序的。

    改变作用域(临时延长作用域链)

    函数每次执行时对应的执行黄环境都是独一无二的! 多次调用同一个函数会创建多个执行环境!当函数执行完毕后,执行环境会被销毁~~~ 每一个运行期执行环境都和一个作用域链关联。 而with 和 catch语句 ,就可以在运行期改变函数的作用域链。 它们会在作用域链的前端添加一个变量对象。 对with语句来说,会将指定的对象添加到作用域链中。 catch则是创建一个新的变量对象。 执行结束后就会被移除,这个变量对象是临时增加的。

    转载请注明原文地址: https://ju.6miu.com/read-10712.html

    最新回复(0)