JS中的声明提升问题

我们习惯将 var a = 2; 看作一个声明,而实际上JavaScript引擎并不这么认为。他将 var a a = 2 当作两个单独的声明,第一个是编译阶段的任务,第二个则是执行阶段的任务。

——《你不知道的Js》

变量提升

变量提升的概念已经为大家所熟知,简单来讲就是在代码执行前编译器会将变量的声明提升至其所在作用域(不是全局作用域)的顶端。但在这过程中还有一些细节需要注意。比如赋值与声明提升的先后关系。先看一个例子。

由于存在变量声明提升,对 a 的声明已经提升至最前,这里打印变量a的值就不会抛出ReferenceError( a is not defined )异常。但是奇怪的是 a 的值为 undefined 这就说明了变量的赋值操作并未随着变量声明的提升而被提升,而是仍被留在原地。就等同于下图的样子。

函数声明提升

跟变量声明的提升一样,只不过声明的不再是变量而是一个函数了。就像这样 var a  = >  function a(){...} 。还是来看例子。

由于存在函数声明提升,函数 foo 被正常执行打印出 a 的值为2。但这里同样有一个细节需要注意。

这里看到,函数声明会被提升,但函数表达式并不会。其中的道理跟上面的变量赋值是一样的。对变量 foo 的声明首先被提升,将一个匿名函数赋值给变量 foo 的操作还被丢在原地。像下面这样。

执行到foo()时,这里的foo只是一个值为 undefined 的小变量,还未被改变为函数呢。对一个 undefined 进行函数调用当然要抛出 TypeError 错误。

说到这里,还有一种具名的函数表达式(非匿名函数表达式),常常被人(我)误解。看例子。

为什么会出现 ReferenceError ? 先从函数的声明方式说起。函数有且只有两种声明方式。

  1. 一般函数声明:function foo(){ }
  2. 函数表达式声明:var foo = function(){ }; 等号后面必须为匿名函数

对于 var foo = function bar(){ }; 这种具名函数表达式声明函数的方式等同于普通函数表达式。但此时的 bar 仅仅作为foo()的一个内部属性,这也就是上例中抛出 ReferenceError 的原因。

时间: 2024-08-11 05:32:07

JS中的声明提升问题的相关文章

js中的变量提升

在js中 变量声明与赋值被认为是两个不同的操作,引擎首先会对前者进行优先编译,这部分工作就是找到所有的声明(例如函数声明function b(注:非函数表达式),变量声明var a),既然是优先执行,那么在一些代码结构中,后声明的function,var 变量就会提前解释: 例如 var a=3:引擎会认为这是两个操作  var a(声明); a=3(赋值),简而言之就是 先有蛋 后有鸡, 理解了这一点 这就很好解释如下的代码结构及其输出 a=2;var a; //定义声明提升console.l

JS中函数声明与函数表达式的不同

Js中的函数声明是指下面的形式: function functionName(){ } 这样的方式来声明一个函数,而函数表达式则是类似表达式那样来声明一个函数,如: var functionName = function(){ } 可能很多朋友在看到这两一种写法时会产生疑惑,这两种写法差不多,在应用中貌似也都是可行的,那他们有什么差别呢? 事实上,js的解析器对函数声明与函数表达式并不是一视同仁地对待的.对于函数声明,js解析器会优先读取,确保在所有代码执行之前声明已经被解析,而函数表达式,如同

js中的变量提升和函数提升

1在js中只有两种作用域 a:全局作用域 b:函数作用域 在ES6之前,js是没有块级作用域. 首先来解释一下什么是没有块级作用域? 所以此时 是可以打印输出变量a的值. 2:什么是变量提升? 在我们的js中,代码的执行时分两步走的,1.解析 2.一步一步执行 那么变量提升就是变量声明会被提升到作用域的最顶上去,也就是该变量不管是在作用域的哪个地方声明的,都会提升到作作用域的最顶上去. 那么上面这种写法其实等价于下面这种写法: 看几个例子: 把上面的例子稍作改动: 结果就会大不一样, 再看一个例

js中变量名提升和函数名提升

首先,js中变量没有块级作用域,但是有函数作用域,即只有函数可以约数变量的作用域. 并且,函数的实质也是一个变量,所以可以改变它的值,即赋值.所以变量名提升和函数名提升非常相像. 1.变量名的提升发生在函数内部.看下面的例子.说明:第一个因为弹出undefined,相当于在上面定义了var num;因为函数内部,定义了var num=20:就相当于在一开始定义了var num;这就是变量名的提升. var num = 10; function func() { alert(num); //und

js中要声明变量吗?

你好,js语言是弱类型语言,无需申明即可直接使用,默认是作为全局变量使用的.建议:在function里时应使用var 申明变量,这样改变量仅仅只在function的生存周期内存在,不会污染到,全局控件.至于直接在<script>标签内使用的话则申明不声明效果都是一样的. 下面的文章可以帮助你更清楚的了解js变量一.变量的类型 Javascript和Java.C这些语言不同,它是一种无类型.弱检测的语言.它对变量的定义并不需要声明变量类型,我们只要通过赋值的形式,可以将各种类型的数据赋值给同一个

关于js中变量声明和作用域的理解

1. var是声明一个变量:虽然声明了这个变量,但在存入值之前,它的初始值是 undefined:2.全局变量:拥有全局作用域,在js代码中的任何地方都是有定义的:3.局部变量:在函数内声明的变量只在函数内有定义,作用域是局部的,只在函数内有定义:4.全局作用域编写代码时可以不写var,但声明局部变量时必须使用var语句;5.在函数体内,局部变量的优先级高于同名的全局变量.如果局部变量和全局变量同名,那么全局变量会被局部变量所遮盖:但全局变量的值不会改变:6.作用域链查找规则:自上而下(一个或多

js中的变量提升与函数提升

先看看一个简单的代码 var str='Hello World'; alert(str);//弹出 Hello World 再看一段代码: var v='Hello World'; (function(){ alert(v); })() //和我们预期的一样,还是弹出 Hello World 那么铺垫完了,继续coding var str='Hello World'; (function(){ alert(str); var str='I love coding...'; })() //出乎我们

js中的变量提升,运算符详解及计算机的进制

变量提升 凡是存到存储空间的变量(用var声明的变量)都有提升的功能.再没有赋值之前就可以使用这个变量,只不过值是undefined.. 运算符 =  赋值运算  var a=5: 把数字5赋值给变量a == 双等号  等于判断  返回的是true和false 主要用于判断 + 加法运算 -减法运算 * 乘法运算 /除法运算 % 取模(求余) ++ 自增每次加一 A++ 先使用变量a用完之后再加1 ++a 先让a加1然后再使用变量a -- A--  先使用变量a再自减1 --a  先自减1 再使

js中变量声明提前

只要是写过点JS代码,很简单一个var 就完事了.那对于JS编译器背后它又发生了什么呢?那就一步步通过代码来讲起. x = 1; alert(x); var y = function() { alert(x); var x = 2; alert(x); } y(); 上面的代码也会你答对了它会分别输出:1,undefined,2.对于我来说,第一反应它会输出:1,1,2.为什么第二个会输出undefined?在上面我明确定义了一个全局变量x,为何找不到? 那是因为:js编译器在执行这个y函数的时