以下代码:
console.log(b);
b = 2;
//"ReferenceError: b is not defined
我以为打印出来会是 undefined。
按我的理解 b = 2 没有使用 var,所以是声明了一个全局变量,既然声明了变量,那就会有变量声明提升,为什么会是ReferenceError: b is not defined 呢?
而尝试加上 var:
console.log(b);
var b = 2;
//undefined
所以这样看来 用 var 和省略 var 不仅仅是局部和全局声明的区别?
新手求教,谢谢!
代码执行总有个先后顺序吧。。。
补充一点:
直接
b = 2
这种创建全局变量的方式,其实质是变为全局对象上的一个属性,即window.b = 2
,所以,这不存在什么提升不提升;使用var声明的变量则存在声明提升。自己再自问自答补充一点:
在 mdn 查到这样一句话:
这句话解释了我关于全局变量 b 为什么不会像 a 一样提升的困惑。a 是声明变量,而 b 是非声明变量,只有在执行时才会定义,所以不会在执行前提升。
原文:https://developer.mozilla.org...
声明会被提前
会被编译器解释成
而 未声明/未定义 则连被提升的机会都没有, 所以一用就报错
这些作用域的问题 你可以看看 《你不知道的javascript》(上卷) 上面都有讲到
引擎---
从头到尾负责整个JavaScript程序的编译及执行过程。
编译器---
引擎的朋友,负责语法分析及代码生成的工作。
作用域---
引擎的另一个朋友,负责收集并维护由所声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。
当你看到var a = 1;
事实上,引擎认为这里有两个完全不同的声明,一个由编译器在编译时处理,另一个由引擎在运行时处理。
var a=1;分解
遇到var a,编译器会询问作用域是否已经有一个该名称的变量存在于同一个作用域的集合中。如果是,编译器会忽略该声明,继续进行编译;否则他会要求作用域在当前作用域的集合中声明一个新的变量,并命名为a。
接下来编译器会为引擎生成运行时所需要的代码,这些代码被用来处理a=1这个赋值操作。引擎运行时首先询问作用域,在当前的作用域集合中是否存在一个叫做a的变量,如果是,引擎就会使用这个变量;如果否,引擎就会继续查找该变量。