废话不说,直接上代码(这是在JavaScript面对对象编程指南上面看到的一个例子)

var a=123;
function f(){
alert(a);
var a=1;
alert(a);
}
f();

  书上的解释是这样的:当JavaScript执行过程进入新函数时,这个函数内被声明的所有变量都会被移动导到函数最开始的地方。这种现象叫做提升。且被提升的只有变量的声明。

上面这个例子可以等价于:

var a=123;
function f(){
  var a;
  alert(a);
  a=1;
  alert(a);
}
f(); //答案很显然是1

  书上只是把它当做一个定义,告诉读者必须记住。其实我们可以从JavaScript编译器的原理出发,搞清楚这段代码到底是怎么编译的就不用死记了!!

  那么我们就首先简单的谈一下JavaScript代码是怎样编译执行的(浅显的谈)首先JavaScript代码的编译执行主要由JavaScript引擎,编译器,作用域三个负责。

  引擎:从头到尾负责整个JavaScript程序的编译和执行过程;

  编译器:负责语法分析及代码生成等;

  作用域:负责收集并维护由所有声明的变量组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些变量的访问权限。

  可能不是很明白,我们先看一下传统的编译器编译的过程,一段代码执行大概需经过下面三个过程(其实际过程肯定比这复杂很多):

  1,词法分析:将由字符组成的字符串分解成有意义的代码块。而这些代码块被称作词法单元。例如:var a=2;这段代码会被分解成var,a,=,2,;这些词法单元。

  2,语法分析:将词法单元流转换成一个由元素逐级嵌套所组成的代表了程序语法结构的“抽象语法树”;

  3,代码生成:将“抽象语法树”转换成为可执行代码的过程。这个过程与语言和目标平台相关。

  由于JavaScript不同于其他有专用编译器的语言如C(如hello.c是先编译成可执行的hello.0程序,这儿阶段声明赋值都已经操作完成,如果编译成功就能执行。)而JavaScript代码编译阶段只是一个对变量的声明阶段,其赋值什么的操作是在代码实际执行的时候才进行的。这也是为什么JavaScript代码写完后必须执行才能知道有没有错误。

  好了相关概念介绍基本差不多了,那上面这段代码该如何用编译器去理解呢!我们先来简单的理解var a=2;这段代码。首先这段代码由交给编译器:编译器工作就是负责语法分析,它首先会对var a进行声明,然后去它的作用域中寻找之前有没有声明a,如果已经声明了就忽略这个声明,如果没有找到就在作用域中声明一个新的变量a,然后编译器就将代码编译成引擎可以运行的代码,这些代码用来处理a=2;引擎拿到代码后首先会在作用域中寻找有没有a变量,如果有就使用这个变量a,如果没有就会抛出错误。这段过程总结一下就是代码首先在编译器中声明相关变量,然后交给引擎,引擎便对这些变量进行操作(赋值等)。

  有了上面的分析过程我们再来看第一段代码:书上之所以能把它改写成下面那段代码,就是因为这段代码首先会在编译器进行编译,编译的过程就是将这段代码中作用域相关的各个变量进行声明,这是在引擎执行代码前工作的,所以改写的时候var a会提到作用域的最前面,等编译完成后JavaScript引擎才会进一步执行代码也就是对变量进行各种赋值等操作。这个过程就是书上面提到那个词“提升”。其他的一些细节就不用赘述了。第二段代码应该能很清楚的理解了。(注意:提升只能在变量自己的作用域里面提升,不能越过作用域提升到外面来。)。

  再给一个练习的例子:

f();  //Hello World!
var f;
function f(){
  aler("Hello World!");  
}
f=function(){
  alert("Hello Javascript!");
}

  改写形式我就不写了,自己完全可以写出来。

  

关于JavaScript变量提升的理解的更多相关文章

  1. JavaScript变量提升的理解

    变量提升 先说三句总结性的话: let 的「创建」过程被提升了,但是初始化没有提升. var 的「创建」和「初始化」都被提升了. function 的「创建」「初始化」和「赋值」都被提升了. 所以,我 ...

  2. 回归基础: JavaScript 变量提升

    from me: javascript的变量声明具有hoisting机制,它是JavaScript一个基础的知识点,也是一个比较容易犯错的点,平时在开发中,大大小小的项目都会遇到. 它是JavaScr ...

  3. JavaScript变量提升和函数声明预解析

    1.首先理解函数作用域 在JavaScript中,变量的定义并不是以代码块作为作用域的,而是以函数作用作用域的.也就是说,如果变量是在某个函数中定义的,那么它在函数以外的地方是不可见的.而如果该变量是 ...

  4. JavaScript变量提升 面试题

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  5. javascript中变量提升的理解

    网上找了两个经典的例子 var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar(); // 10 var ...

  6. 对javascript变量提升跟函数提升的理解

    在写javascript代码的时候,经常会碰到一些奇怪的问题,例如: console.log(typeof hello); var hello = 123;//变量 function hello(){ ...

  7. 最通俗易懂的javascript变量提升

    a = 'ghostwu'; var a; console.log( a ); 在我没有讲什么是变量提升,以及变量提升的规则之前, 或者你没有学习过变量提升,如果按照现有的javascript理解, ...

  8. JavaScript变量提升及作用域

    今天在知乎看前端面试题的时候,看到这样的问题,发现自己懂的真的是太少了,看了给的例子,所以写一下自己的理解. 首先放一段代码: var v= “hello JavaScript”; alert(v); ...

  9. JavaScript: 变量提升和函数提升

    第一篇文章中提到了变量的提升,所以今天就来介绍一下变量提升和函数提升.这个知识点可谓是老生常谈了,不过其中有些细节方面博主很想借此机会,好好总结一下. 今天主要介绍以下几点: 1. 变量提升 2. 函 ...

随机推荐

  1. 在SharePoint 2010中,如何找回丢失的服务账号(Service Account)密码

    背景信息: 通常在SharePoint环境中我们会使用很多的服务账号来运行各种不同的服务,尤其在企业环境中,由于权限管理条例严格,这些服务账号更是只能多不能少.面对如此多的服务账号,各个企业都会有自己 ...

  2. 培训SQLServer 嵌套事务PPT分享

    培训SQLServer 嵌套事务PPT分享 下载地址 http://files.cnblogs.com/files/lyhabc/SQLServer%E5%B5%8C%E5%A5%97%E4%BA%8 ...

  3. 数据库中的two phase locking

    数据库中的two phase locking 两段锁协议是指每个事务的执行可以分为两个阶段:生长阶段(加锁阶段)和衰退阶段(解锁阶段). 加锁阶段:在该阶段可以进行加锁操作.在对任何数据进行读操作之前 ...

  4. 《深入理解Java虚拟机》Java内存区域与内存溢出异常

    注:“蓝色加粗字体”为书本原语 先来一张JVM运行时数据区域图,再接下来一一分析各区域功能:   程序计数器 程序计数器(program Counter Register)是一块较小的内存空间,它可以 ...

  5. ASP.NET Core 1.0 静态文件、路由、自定义中间件、身份验证简介

    概述 ASP.NET Core 1.0是ASP.NET的一个重要的重新设计. 例如,在ASP.NET Core中,使用Middleware编写请求管道. ASP.NET Core中间件对HttpCon ...

  6. LINQ系列:LINQ to XML类

    LINQ to XML由System.Xml.Linq namespace实现,该namespace包含处理XML时用到的所有类.在使用LINQ to XML时需要添加System.Xml.Linq. ...

  7. ImageView设置边框的两种方式

    转载:http://www.2cto.com/kf/201308/239945.html package cc.testimageviewbounds; import android.os.Bundl ...

  8. Android探索之Service全面回顾及总结

    什么是Service? Service(服务)是Android提供的四大组件之一,是一个没有用户界面的在后台运行执行耗时操作的应用组件.其他应用组件能够启动Service,并且当用户切换到另外的应用场 ...

  9. 精确率与召回率,RoC曲线与PR曲线

    在机器学习的算法评估中,尤其是分类算法评估中,我们经常听到精确率(precision)与召回率(recall),RoC曲线与PR曲线这些概念,那这些概念到底有什么用处呢? 首先,我们需要搞清楚几个拗口 ...

  10. iOS开发之窥探UICollectionViewController(三) --使用UICollectionView自定义瀑布流

    上篇博客的实例是自带的UICollectionViewDelegateFlowLayout布局基础上来做的Demo, 详情请看<iOS开发之窥探UICollectionViewControlle ...