原文链接:http://www.jianshu.com/p/330b1505e41d

在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: {...},  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 }

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

转载于:https://www.cnblogs.com/vleexy/p/6392945.html

JavaScript通俗易懂(一)-变量提升相关推荐

  1. JavaScript 作用域、变量提升

    JavaScript 作用域 JavaScript 作用域 JavaScript 局部作用域 JavaScript 全局变量 JavaScript 变量生命周期 函数参数 HTML 中的全局变量 ES ...

  2. javascript --- [小练习]变量提升、优先级综合

    求下列函数输出结果 function Foo() {getName = function() {console.log(1)}return this } Foo.getName = function( ...

  3. JavaScript 笔记(2) -- 类型转换 正则表达 变量提升 表单验证

    目录:  typeof, null, undefined, valueOf() 类型转换 正则表达式 错误: try, catch, throw 调试工具 变量提升 strict 严格模式 使用误区 ...

  4. JavaScript中变量提升是什么?如何实现?

    在进行web前端开发的时候,我们经常会遇到变量提升的情况,那么JS在解析变量的时候是如何做到提升的呢?今天小千就来带大家了解一下. 首先在JS中涉及两种作用域的问题,那么什么是作用域呢? 作用域是代码 ...

  5. JavaScript中的预解析(变量提升)介绍!

    今天小千为大家介绍一下JavaScript中的预解析(变量提升).从什么是预解析及变量的预解析和函数的预解析及加载流程进行学习(注意:我们这里说的ES5中的预解析). 什么是解析 首先代码执行肯定需要 ...

  6. JavaScript中函数的变量提升问题

    函数的大体分三种,一种是函数的声明,一种是函数表达式(又称为函数的字面量) 1.函数的声明 => function myFn(){}; 2.函数的表达式 => var myFn = fun ...

  7. 未定义函数或变量_变量提升:JavaScript是顺序执行,为什么变量在定义之前执行不会报错而是报Underfined...

    showName() console.log(myname) var myname = 'hhh' function showName() {console.log('函数showName被执行'); ...

  8. javascript变量提升/函数提升

    首先 javascript 是一种弱类型.动态的.解释型的脚本语言. 弱类型:类型检查不严格,偏向于容忍隐式类型转换. 强类型:类型检查严格,偏向于不容忍隐式类型转换. 动态类型:运行的时候执行类型检 ...

  9. JavaScript 变量提升

    JavaScript 变量提升 JavaScript 中,函数及变量的声明都将被提升到函数的最顶部. JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明. 这几天在刷题的过程中 ...

最新文章

  1. NEWS - InstallShield 2013 SP1发布
  2. VS Debug必备技能
  3. Spring Boot2.x-08Spring Boot2.1.2 整合 Mybatis1.3.2 + 通用Mapper2.1.4 + PageHelper1.2.10 + Druid 1.1.10
  4. 推荐系统中多值特征的八大处理技巧
  5. SET QUERY_GOVERNOR_COST_LIMIT
  6. Unity降版本的蛋疼操作
  7. 昨天的一个披扣的问题处理到很晚没搞定的原因
  8. oracle model类型,Oracle SQL高级编程——Model子句全解析-Oracle
  9. linux使用tar命令打包压缩时排除某个文件夹或文件
  10. notifier chain — 内核通知链【转】
  11. 迭代时移除List中的元素的正确方式
  12. 31省份及直辖市自治区的下拉框代码
  13. Altium Designer
  14. 【iPod转换精灵V10.2 官方最新版】强大的视频转换功能
  15. MATLAB与STK互联23:卫星对象操作(14)—仿真分析案例1,建立8个地面站,分析对卫星的可见性
  16. 施乐j75服务器电源管理系统,富士施乐推出印刷系统 Color J75 Press
  17. 网上车市通过聆讯:营收单一,上半年减员15%,徐翀持股80%
  18. 卸载过 IE浏览器,再安装提示“安装程序无法继续,因为你的计算机上安装了新的 Internet Explorer” ,cv 别人的IE浏览器安装文件夹打开 iexplore.exe 窗口闪一下又关掉了
  19. FME会员期刊(2012冬季版)
  20. STM32F4寄存器初始化系列:GPIO

热门文章

  1. 晨哥真有料丨明知道没有结果的爱情,还要继续下去吗?
  2. python截图直接在内存里调用_Python-按块上传FTP中的内存文件(由API调用生...
  3. java netty modbus协议接收iot数据
  4. c语言边界条件的设置,求解能不能用c或c++语言实现下面的约束条件
  5. Golang实践录:使用gin框架实现转发功能:利用nginx转发
  6. onvif学习笔记8:最近写的一个ONVIF客户端的心得小结
  7. PHP实现的服务器端,用PHPStorm实现在本地实时编辑服务器端的代码
  8. 【clickhouse】MergeTree storage require data path INCOORRECT_FILE_NAME
  9. 【算法】斐波那契数列
  10. 10-11-010-简介-架构-架构简介