关于JavaScript变量提升的理解

  废话不说,直接上代码(这是在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!");}

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

  

时间: 2024-10-05 06:13:32

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

回归基础: JavaScript 变量提升

from me: javascript的变量声明具有hoisting机制,它是JavaScript一个基础的知识点,也是一个比较容易犯错的点,平时在开发中,大大小小的项目都会遇到. 它是JavaScript引擎在执行的时候,把所有变量的声明都提升到当前作用域的最前面. 当然了,函数声明也是可以被提升的.然后,函数表达式却没有提升. 原文:Back to Basics: JavaScript Hoisting 译文:回归基础: JavaScript 变量提升 变量声明是所有的编程语言中最基础部分之

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

在写javascript代码的时候,经常会碰到一些奇怪的问题,例如: console.log(typeof hello); var hello = 123;//变量 function hello(){//函数声明 } console.log(typeof hello); var hello = function(){//函数表达式 } console.log(typeof hello);//function number function 对于为什么会是这样的一个结果:function numb

JavaScript变量提升及作用域

今天在知乎看前端面试题的时候,看到这样的问题,发现自己懂的真的是太少了,看了给的例子,所以写一下自己的理解. 首先放一段代码: var v= "hello JavaScript"; alert(v); 很明显,这样的是会弹出对话框: 将alert(v)写到一个函数中: var v= "hello JavaScript"; function test(){ alert(v); }; test(); 这样弹出的结果肯定也是和第一个一样:那么下面这种方式输出的结果是什么?

javascript变量提升详解

js变量提升 对于大多数js开发者来说,变量提升可以说是一个非常常见的问题,但是可能很多人对其不是特别的了解.所以在此,我想来讲一讲. 先从一个简单的例子来入门: a = 2; var a; console.log(a); 你觉得以上的代码会输出什么?是输出undefined吗?如果是按照程序的自上而下执行的话,那么这一段代码确实是输出undefined.然而,javascript并不是严格的自上而下执行的语言. 这一段代码的输出结果是2,是不是感到很意外?为什么会这样呢?这个问题的关键就在于变

JavaScript 变量提升

变量提升(Hoisting):在ES6之前,函数声明和变量声明总是被JavaScript解释器隐式地提升(hoist)到包含他们的作用域的最顶端. 注意: 1. JavaScript 仅提升声明,而不提升初始化.2. ES6 中不存在变量提升的概念. 1. 变量提升 变量未声明: function fn () { console.log(name); } fn(); // 报错: ReferenceError: name is not defined 变量在使用后声明: function fn

JavaScript变量提升

此文章首发于segmentfault,若有转载引用,请务必私信告知,并注明出处:https://segmentfault.com/q/1010000005921127 变量的问题,莫过于声明和赋值两个步骤,而这两个步骤是分开的. 函数声明被提升时,声明和赋值两个步骤都会被提升,而普通变量却只能提升声明步骤,而不能提升赋值步骤. 变量被提升过后,先对提升上来的所有对象统一执行一遍声明步骤,然后再对变量执行一次赋值步骤.而执行赋值步骤时,会优先执行函数变量的赋值步骤,再执行普通变量的赋值步骤.当你明

JavaScript变量提升演示样例

直接先看两段代码 function getSum() { var sum = a + b; var a = 1; var b = 2; return sum; } getSum(); function getSum() { var sum = a + b; a = 1; b = 2; return sum; } getSum(); 大家能够先看一下这两段代码的异同,并推断一下运行后分别得到的结果. 在运行第一段代码时,得到的NaN,这是由于在函数中变量声明被提升的结果.在运行"sum = a +

JavaScript变量提升示例

直接先看两段代码 function getSum() { var sum = a + b; var a = 1; var b = 2; return sum; } getSum(); function getSum() { var sum = a + b; a = 1; b = 2; return sum; } getSum(); 大家可以先看一下这两段代码的异同,并判断一下执行后分别得到的结果. 在执行第一段代码时,得到的NaN,这是因为在函数中变量声明被提升的结果,在执行"sum = a +

JavaScript 变量和函数提升问题总结

一 什么是JavaScript 变量提升? -- JS程序运行时, (a)变量的声明会被解释器"提升"到方法体内的顶部,初始化赋值操作不提升按顺序执行 (b)函数体内未声明的变量,解释器会在函数体外声明变量,成为全局变量 (c)声明过的函数,整个函数体会被解释器提升到方法体的顶部,初始化赋值操作按顺序执行 1-1 变量提升 eg:变量的声明提升,初始化赋值不提升. <script> console.log(a); // undefined var a=3; // 若没有va