console.log(a)
var a = 8;
//------编译阶段会进行变量提升,形成下面的代码--------
var a;
console.log(a); // undefined
a = 8;
在编译阶段会将是有使用var的变量进行变量提升,提前声明,这就是为什么明明我们在它声明前输出它不会报错,只是值为undefined而已。同时var还有另外一个特性,就是如果你是在全局(顶级)作用域下进行进行声明的话会将这个变量与 顶级对象(浏览器即为 window 对象) 建立联系,并且可以通过 window.** 的方式获取你用 var 声明的变量(全局作用域声明过的)。
同时如果在同一个作用域下对某个变量进行多次 var 声明时,编译不管你声明多少次都会统一看成一次声明。
var a = 8;
console.log(a);
var a = 9;
// 等价于下面的代码
var a;
a = 8;
console.log(a);
a = 9;
let
let 是 ES6 新增的一种新的变量声明的方式,它和var有着一定的差异,就是使用 let声明的变量并不会进行变量提升,如果在它声明前调用的话会照成报错,这种报错就是所谓的暂时性死区照成的。
console.log(a); // a is not defined 暂时性死区
let a = 8;
同时使用 let 和 var不一样的是在同一个作用域下不可以对已经声明过的变量(不管是使用var,let或者const或者是function)在继续进行声明,否则也会报错。
var a = 1;
let a = 2; // Identifier 'a' has already been declared
还有就是 let 在声明变量的时候回创建一个私有的作用域,因为作用域链查找是从内到外的,所以外部作用域是无法获取和操作这个变量的,除非他们在同一个作用域,就如同下面的代码:
{
let a = 'CodeRookie262';
console.log(a); // CodeRookie262
}
console.log(a); // Uncaught ReferenceError: a is not defined
const
const 顾名思义就是用来声明一个常量的,一个不变的值,它和 let 一样不可以在同一个作用域下对同一个变量进行多次声明,且生成一个私有作用域,还有可以对其进行再次赋值。但是就有一个问题,为什么我使用const声明一个变量并且定义为一个对象时为什么可以更改这个对象的属性呢?
其实const说的是不可更改声明定义是所指定的内存地址,如果你是赋值基本类型的话,那么这个基本类型直接挂钩对应的内存地址了导致不可以更改对其他值;如果你赋值的是一个对象,给与变量的是一个堆的内存地址,你对这个堆中的对象做增删操作都没事,因为你的操作并不会改变堆的内存地址,而如果你直接在重新给这个变量在赋值一个新的对象时就会发生报错,因为你的操作属于更改它所绑定的“值”了。
var,let以及const都是变量声明的一种方式,虽然都是声明变量,但是声明中存在着一定的差异性。
var
使用 var 声明的变量会在
编译阶段
中进行变量提升,可以看看下面的代码在编译阶段会将是有使用
var
的变量进行变量提升,提前声明,这就是为什么明明我们在它声明前输出它不会报错,只是值为undefined
而已。同时var
还有另外一个特性,就是如果你是在全局(顶级)作用域下进行进行声明的话会将这个变量与 顶级对象(浏览器即为 window 对象) 建立联系,并且可以通过 window.** 的方式获取你用var
声明的变量(全局作用域声明过的)。同时如果在同一个作用域下对某个变量进行多次
var
声明时,编译不管你声明多少次都会统一看成一次声明。let
let
是ES6
新增的一种新的变量声明的方式,它和var
有着一定的差异,就是使用let
声明的变量并不会进行变量提升,如果在它声明前调用的话会照成报错,这种报错就是所谓的暂时性死区
照成的。同时使用
let
和var
不一样的是在同一个作用域下不可以对已经声明过的变量(不管是使用var
,let
或者const
或者是function
)在继续进行声明,否则也会报错。还有就是
let
在声明变量的时候回创建一个私有的作用域,因为作用域链查找是从内到外的,所以外部作用域是无法获取和操作这个变量的,除非他们在同一个作用域,就如同下面的代码:const
const
顾名思义就是用来声明一个常量的,一个不变的值,它和let
一样不可以在同一个作用域下对同一个变量进行多次声明,且生成一个私有作用域,还有可以对其进行再次赋值。但是就有一个问题,为什么我使用const
声明一个变量并且定义为一个对象时为什么可以更改这个对象的属性呢? 其实const
说的是不可更改声明定义是所指定的内存地址,如果你是赋值基本类型的话,那么这个基本类型直接挂钩对应的内存地址了导致不可以更改对其他值;如果你赋值的是一个对象,给与变量的是一个堆的内存地址,你对这个堆中的对象做增删操作都没事,因为你的操作并不会改变堆的内存地址,而如果你直接在重新给这个变量在赋值一个新的对象时就会发生报错,因为你的操作属于更改它所绑定的“值”了。