前端基础进阶: 变量对象

昭容
• 阅读 896

我们已经知道,在调用一个函数时, 一个新的执行上下文将会被创建, 而一个执行上下文的周期分为两个阶段

  • 创建阶段: 在这个阶段,执行上下文将会分别创建变量对象, 建立作用域链, 确定this指向
  • 执行阶段: 创建完成后, 就会执行代码, 这时候会完成变量赋值,函数引用, 以及一些其他代码

前端基础进阶: 变量对象

从这里我们可以看到, 执行上下文时涉及到了变量对象, 作用域链, this指向等很多重要的概念. 这里我们主要理解变量对象

变量对象

变量对象的创建经历以下三个过程:

  • 建立argument对象. 检查当前上下文中的参数, 建立该对象的属性和属性值
  • 检查当前上下文的函数声明.也就是使用function关键字声明的函数.在变量对象中,以函数名作为一个属性, 属性值指向该函数所在内存地址的一个引用. 如果该函数名属性已经存在, 则该属性将会被新的引用所覆盖
  • 检查当前上下文的变量声明.每找到一个变量声明,就在变量对象中以变量名建立一个属性, 属性值为undefined.如果该变量名的属性已经存在,则会直接跳过,原属性值不会发生变化

前端基础进阶: 变量对象
根据这个规则,理解变量提升就变得更加简单, 可以使用变量对象的创建过程来解释变量提升

比如下面例子

console.log(foo) // function foo (){}
function foo (){}
var foo = 20
// 上述代码的执行顺序为
// 首先将所有函数声明放入变量对象中
function foo () {}
// 其次将所有变量声明放入变量对象中, 但是foo已经存在同名函数,则foo = undefined会跳过
// var foo = undefined 
console.log(foo)
foo = 20;

从上面的规则可以看出,function的声明会比var声明的优先级更高一些.
看下下面部分例子

// demo01
function test() {
    console.log(a);
    console.log(foo());

    var a = 1;
    function foo() {
        return 2;
    }
}

test();

执行顺序

function test() {
    function foo(){
        return 2
    }
    var a = undefined;
    console.log(a)
    console.log(foo())
    a = 1;
}
test();

在上述例子中, 从test()调用时, test的执行上下文开始创建.

// 创建过程
testEC = {
    // 变量对象
    VO: {},
    // 作用域链
    scopeChain: {}
}
// 本文只讨论变量对象VO
VO = {
    argument: {...},
    foo: <foo的引用地址>,
    a: undefined
}

未进入执行阶段时, 变量对象中的属性都不可以被访问.但是进入执行阶段,变量对象转为了活动对象,里面的对象都可以访问了,然后开始进行执行阶段的操作

如果被问到变量对象和活动对象的区别, 其实他们都是一个对象,只是出于执行上下文的不同生命周期内.只有出于函数调用栈栈顶的执行上下文中的对象,才会变成活动对象.
// 执行阶段
VO = {
    argument: {...},
    foo: <foo的引用地址>,
    a: 1,
    this: window
}

全局上下文的对象

以浏览器为例, 全局对象为window
全局对象的变量对象就是window对象.this也是指向window

// 全局对象
windowEC = {
    VO: window,
    scopeChain: {},
    this: window
}

全局上下文的生命周期和程序的生命周期保持一致. 只要程序不停止运行, 比如关掉浏览器窗口, 全局上下文就会一直存在.

点赞
收藏
评论区
推荐文章
Souleigh ✨ Souleigh ✨
4年前
JS - 作用域
一、作用域作用域,即变量(变量作用域又称上下文)和函数生效(能被访问)的区域或集合换句话说,作用域决定了代码区块中变量和其他资源的可见性举个例子function myFunction(){    let inVariable  "函数内部变量";}myFunction();//要先执行这个函数,否则根本不知
Karen110 Karen110
3年前
一篇文章带你了解JavaScript作用域
在JavaScript中,对象和函数也是变量。在JavaScript中,作用域是你可以访问的变量、对象和函数的集合。JavaScript有函数作用域:这个作用域在函数内变化。一、本地JavaScript变量一个变量声明在JavaScript函数内部,成为函数的局部变量。局部变量有局部作用域:它们只能在函数中访问。JS://codeherecann
Wesley13 Wesley13
3年前
java成员变量的初始化
类变量(static变量,不需要实例化对象也可以引用)实例变量(非static变量,需要实例化对象)局部变量(类的成员函数中的变量)初始化方式:构造函数初始化变量声明时初始化代码块初始化java自动初始化(在构造函数执行之前执行) java保证所有变量被使用之前都是经过初始化的(声明并且定义过,被赋值
Wesley13 Wesley13
3年前
java多线程(二)
一、摘要   当我们将线程创建并start时候,它不会一直占据着cpu执行,而是多个线程间会去执行着这个cpu,此时这些线程就会在多个状态之间进行着切换。  在线程的生命周期中,它会有5种状态,分别为:创建、准备、执行、阻塞、死亡二、线程生命周期状态详解  1、创建状态:其实就是newThread()创建了线程对象,这个时候JVM会为其分
御弟哥哥 御弟哥哥
4年前
彻底理解js的作用域链
在之前的文章(https://www.helloworld.net/p/G4dFV7tALU4J)中我已经介绍了执行上下文的变量对象。在这一篇文章我要介绍执行上下文的作用域链了。执行上下文.作用域链(scopechain)作用域链与变量对象有着密不可分的关系,因为作用域链就是变量对象的数组!其中第
御弟哥哥 御弟哥哥
4年前
彻底理解js的执行上下文,以及变量对象
在js中,执行上下文(ExecutionContext)是非常重要的一种对象,它保存着函数执行所需的重要信息,其中有三个属性:变量对象(variableobject),作用域链(scopechain),this指针(thisvalue),它们影响着变量的解析,变量作用域和函数this的指向。上下文栈(ExecutionContextS
Wesley13 Wesley13
3年前
JS 闭包(内存溢出与内存泄漏)(垃圾回收机制)
1.有关闭包定义闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量闭包的特性:函数内再嵌套函数内部函数可以引用外层的参数和变量参数和变量不会被垃圾回收机制回收
Stella981 Stella981
3年前
Javascript解析机制 执行机制
HTML5学堂:在学习JavaScript过程中,我们需要了解事件的机制是怎么执行的?本文将会提到JavaScript事件机制的解析,希望对大家有帮助!javascript解析的过程主要分为两个阶段,分别是编译与执行阶段。在编译期,javascript解释器将完成对javascript代码的预处理,即将javascript代码转换为字节码。在执行
Wesley13 Wesley13
3年前
Java提高篇——静态代码块、构造代码块、构造函数以及Java类初始化顺序
静态代码块:用staitc声明,jvm加载类时执行,仅执行一次构造代码块:类中直接用{}定义,每一次创建对象时执行。执行顺序优先级:静态块,main(),构造块,构造方法。构造函数publicHelloA(){//构造函数}关于构造函数,以下几点要注意:1.对象一建立,就会调用与之相应的构造
小万哥 小万哥
1年前
Go 语言函数、参数和返回值详解
函数是一组语句,可以在程序中重复使用。函数不会在页面加载时自动执行。函数将通过调用函数来执行。创建函数要创建(通常称为声明)一个函数,请执行以下操作:使用func关键字。指定函数的名称,后跟括号()。最后,在花括号内添加定义函数应执行的代码。语法Gofun
GeorgeGcs GeorgeGcs
1天前
【HarmonyOS 5】鸿蒙页面和组件生命周期函数
鸿蒙开发能力HarmonyOSSDK应用服务鸿蒙金融类应用(金融理财一、生命周期阶段:创建阶段build:构建组件的UI结构和样式。onDidBuild:build方法执行完毕后调用,可用于数据初始化或额外的UI调整。挂载阶段onPageShow:页面显示