JS变量对象详解

开年之后工作热情一直不是很高,这几天一直处于消极怠工状态。早上不想起床,起床了不想上班。明明放假之前工作热情还一直很高,一直心心念念的想把小程序项目怼出来,结果休假回来之后画风完全不一样了。我感觉自己得了严重了节后综合征。还好撸了几篇文章,勉强表示这一周的时间没有完全浪费。这篇文章要给大家介绍的是变量对象。

在JavaScript中,我们肯定不可避免的需要声明变量和函数,可是JS解析器是如何找到这些变量的呢?我们还得对执行上下文有一个进一步的了解。

在上一篇文章中,我们已经知道,当调用一个函数时(激活),一个新的执行上下文就会被创建。而一个执行上下文的生命周期可以分为两个阶段。

  • 创建阶段
    在这个阶段中,执行上下文会分别创建变量对象,建立作用域链,以及确定this的指向

  • 代码执行阶段
    创建完成之后,就会开始执行代码,这个时候,会完成变量赋值,函数引用,以及执行其他代码。

执行上下文生命周期

从这里我们就可以看出详细了解执行上下文极为重要,因为其中涉及到了变量对象,作用域链,this等很多人没有怎么弄明白,但是却极为重要的概念,因此它关系到我们能不能真正理解JavaScript。在后面的文章中我们会一一详细总结,这里我们先重点了解变量对象。

变量对象(Variable Object)

变量对象的创建,依次经历了以下几个过程。

  1. 建立arguments对象。检查当前上下文中的参数,建立该对象下的属性与属性值。

  2. 检查当前上下文的函数声明,也就是使用function关键字声明的函数。在变量对象中以函数名建立一个属性,属性值为指向该函数所在内存地址的引用。如果函数名的属性已经存在,那么该属性将会被新的引用所覆盖。

  3. 检查当前上下文中的变量声明,每找到一个变量声明,就在变量对象中以变量名建立一个属性,属性值为undefined。如果该变量名的属性已经存在,为了防止同名的函数被修改为undefined,则会直接跳过,原属性值不会被修改。

我知道有的人不喜欢看文字

根据这个规则,理解变量提升就变得十分简单了。在很多文章中虽然提到了变量提升,但是具体是怎么回事还真的很多人都说不出来,以后在面试中用变量对象的创建过程跟面试官解释变量提升,保证瞬间提升逼格。

在上面的规则中我们看出,function声明会比var声明优先级更高一点。为了帮助大家更好的理解变量对象,我们结合一些简单的例子来进行探讨。

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

在上例中,我们直接从test()的执行上下文开始理解。全局作用域中运行test()时,test()的执行上下文开始创建。为了便于理解,我们用如下的形式来表示

创建过程
testEC = {
// 变量对象
VO: {},
scopeChain: {},
this: {}
} // 因为本文暂时不详细解释作用域链和this,所以把变量对象专门提出来说明 // VO 为 Variable Object的缩写,即变量对象
VO = {
arguments: {...}, //注:在浏览器的展示中,函数的参数可能并不是放在arguments对象中,这里为了方便理解,我做了这样的处理
foo: <foo reference> // 表示foo的地址引用
a: undefined
}

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

这样,如果再面试的时候被问到变量对象和活动对象有什么区别,就又可以自如的应答了,他们其实都是同一个对象,只是处于执行上下文的不同生命周期。

// 执行阶段
VO -> AO // Active Object
AO = {
arguments: {...},
foo: <foo reference>,
a: 1
}

因此,上面的例子demo1,执行顺序就变成了这样

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

再来一个例子,巩固一下我们的理解。

// demo2
function test() {
console.log(foo);
console.log(bar); var foo = 'Hello';
console.log(foo);
var bar = function () {
return 'world';
} function foo() {
return 'hello';
}
} test();
// 创建阶段
VO = {
arguments: {...},
foo: <foo reference>,
bar: undefined
}
// 这里有一个需要注意的地方,因为var声明的变量当遇到同名的属性时,会跳过而不会覆盖
// 执行阶段
VO -> AO
VO = {
arguments: {...},
foo: 'Hello',
bar: <bar reference>
}

需要结合上面的知识,仔细对比这个例子中变量对象从创建阶段到执行阶段的变化,如果你已经理解了,说明变量对象相关的东西都已经难不倒你了。

全局上下文的变量对象

以浏览器中为例,全局对象为window。
全局上下文有一个特殊的地方,它的变量对象,就是window对象。而这个特殊,在this指向上也同样适用,this也是指向window。

// 以浏览器中为例,全局对象为window
// 全局上下文
windowEC = {
VO: window,
scopeChain: {},
this: window
}

除此之外,全局上下文的生命周期,与程序的生命周期一致,只要程序运行不结束,比如关掉浏览器窗口,全局上下文就会一直存在。其他所有的上下文环境,都能直接访问全局上下文的属性。

JS变量对象详解的更多相关文章

  1. 前端高质量知识(三)-JS变量对象详解

    在JavaScript中,我们肯定不可避免的需要声明变量和函数,可是JS解析器是如何找到这些变量的呢?我们还得对执行上下文有一个进一步的了解. 在上一篇文章中,我们已经知道,当调用一个函数时(激活), ...

  2. js变量类型详解

    <html> <title>js变量类型详解</title> <meta http-equiv="content-type" conten ...

  3. JS DATE对象详解

    1.建立时间对象:可获取年,月,日,星期,时,分,秒 var d = new Date(); console.log(d.getFullYear()+'年'+d.getMonth()+'月'+d.ge ...

  4. JS window对象详解

    window 是客户端浏览器对象模型的基类,window 对象是客户端 JavaScript 的全局对象.一个 window 对象实际上就是一个独立的窗口,对于框架页面来说,浏览器窗口每个框架都包含一 ...

  5. JS中的event 对象详解

    JS中的event 对象详解   JS的event对象 Event属性和方法:1. type:事件的类型,如onlick中的click:2. srcElement/target:事件源,就是发生事件的 ...

  6. js对象详解(JavaScript对象深度剖析,深度理解js对象)

    js对象详解(JavaScript对象深度剖析,深度理解js对象) 这算是酝酿很久的一篇文章了. JavaScript作为一个基于对象(没有类的概念)的语言,从入门到精通到放弃一直会被对象这个问题围绕 ...

  7. js课程 1-3 Javascript变量类型详解

    js课程 1-3  Javascript变量类型详解 一.总结 一句话总结:js对象点(属性方法),json对象冒号(属性方法).属性和方法区别只有一个括号. 1.json对象中的函数的使用? 函数名 ...

  8. 《Node.js开发实战详解》学习笔记

    <Node.js开发实战详解>学习笔记 ——持续更新中 一.NodeJS设计模式 1 . 单例模式 顾名思义,单例就是保证一个类只有一个实例,实现的方法是,先判断实例是否存在,如果存在则直 ...

  9. ES6,ES2105核心功能一览,js新特性详解

    ES6,ES2105核心功能一览,js新特性详解 过去几年 JavaScript 发生了很大的变化.ES6(ECMAScript 6.ES2105)是 JavaScript 语言的新标准,2015 年 ...

随机推荐

  1. 《Java I/O 从0到1》 - 第Ⅰ滴血 File

    前言 File 类的介绍主要会依据<Java 编程思想>以及官网API .相信大家在日常工作中,肯定会遇到文件流的读取等操作,但是在搜索过程中,并没有找到一个介绍的很简洁明了的文章.因此, ...

  2. 用label实现横向瀑布流的方法

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAXcAAAKxCAIAAAAn+3udAAAKqWlDQ1BJQ0MgUHJvZmlsZQAASImVlg

  3. c#中insert Geography的字段,包含事务

    SqlConnection conn = new SqlConnection(); conn.ConnectionString ="你的sql server数据库连接字符串"; c ...

  4. LeetCode: 29. Divide Two Integers (Medium)

    1. 原题链接 https://leetcode.com/problems/divide-two-integers/description/ 2. 题目要求 给出被除数dividend和除数divis ...

  5. 基于套接字通信的简单练习(FTP)

    本项目基于c/s架构开发(采用套接字通信,使用TCP协议) FTP-Socket"""__author:rianley cheng""" 功 ...

  6. clr via c#读书笔记五:常量和字段

    1.常量是值从不变化的符号.只能定义编译器识别的基元类型的常量.如:Boolean,Char,Byte,SByte,Int16,UInt16,Int32,UInt32,Int64,Single,Dou ...

  7. spring源码-bean之加载-2

    一.前面说了bean的容器初始化,后面当然是说bean的加载.这里还是不讲解ApplicationContext的bean的加载过程,还是通过最基础的XmlBeanFactory来进行讲解,主要是熟悉 ...

  8. Selenium 入门到精通系列:三

    Selenium 入门到精通系列 PS:Driver_Element 常用方法 例子 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Date : 2 ...

  9. 安迪的第一个字典 (Andy's First Dictionary,UVa10815)

    题目描述: #include<iostream> #include<string> #include<set> #include<sstream> us ...

  10. Flex 布局浅析

    除了 CSS 中传统的布局系统之外,CSS3还提供了一个新布局系统.在这个新的框模型中,框的子代采用水平或垂直布局,而且可将未使用的空间分配给特定的子代,或者通过“弹性”分配给应展开的子代,在各子代间 ...