JavaScript声明变量的方式有三种:var、let、const(es6新增let和const关键词来声明变量).

一、var

var是我们初学js时经常使用的一种声明变量的方式.

  1. var可以进行变量提升(预解析),只提升变量声明,不提升变量赋值.
  2. var可以进行变量的重复定义(后定义的值会覆盖原先定义的值).
  3. var定义的变量,只有在function当中定义外部无法访问,其他比如在for,if,while内部定义的都可以在外部进行访问.
  4. var定义的变量的作用域是window,可以用"window.变量名"来进行调用(一般都会省略简写).

二、let (es6新增)

let是es6新增的一种定义变量的方式,开发当中大量会用到.

  1. let不能进行变量的提升,不能进行变量的重复定义,也不能定义其他(var,const)方式已经定义过得变量.
  2. let定义变量会有临时死区(在let变量未定义之前的区域都称作临时死区,即在这些区域当中不能够访问到let所声明的变量).
  3. let定义的变量会形成一个块级作用域,在for,if,while内部定义变量在外部无法进行访问.类似函数内部的变量,这也是形成闭包的一种方式.
  4. let定义的变量作用域属于global,所以不能用"window.变量名"来调用;而global不会暴露在全局当中,所以也无法通过"global.变量名"来调用.

三、const (es6新增)

const也是es6所新增的定义变量的方式,一般在定义常量的时候使用.

  1. const一般是用来定义常量(1,2,a,b…),一旦定义,不能修改.
  2. const声明变量必须赋值,否则直接报错.
  3. 开发中,我们约定俗成的将const定义的变量名全部大写.
  4. const 如果定义的是对象、数组、函数、引用数据类型。可以改变其中的存储的数据.

const也可以定义变量,本质上保证变量指向的内存地址不发生改变即可.用const定义基本数据类型,由于它们本身值是不可变的,修改只是内存地址会发生变化,所以不能修改
const定义引用数据类型**:本身它们的值是可变的,所以内存地址不会发生变化,只是其中的值进行了更改,所以可以进行修改.

//一般用于定义常量,不能修改
const b = 3;		
//可以定义基本数据类型,但不能修改
const a = 'tom';
a = 'zxc';           //报错 Assignment to constant variable
//可以定义引用数据类型,可以进行修改
const list = [1,2,3,4];
list[1] = 'zxc';
console.log(list)    //[1,'zxc',3,4]
和let的相同点:
  1. 变量作用域都属于global,都有临时死区,都会形成块级作用域使外部无法访问.
  2. 都不能进行变量的提升,不能定义其他(var,let)方式已经定义过得变量.

注意点:在js当中不定义直接进行赋值的变量(隐式声明),作用域永远属于全局,可以在任何地方访问到该变量

function fn() {
     b = 3;
}
fn();
console.log(b);         //3

不过这种隐式定义的方式在开发当中基本不会去使用,如果开发当中需要外部访问内部变量,可以将window当做参数传入函数当中或者直接在函数内将变量传给window.

将window当做参数传入函数

(function fn1(win) {
	var n = 10;
    win.n = n;
})(window);
console.log(n);		//10

直接在函数内将变量传给window.

(function fn2() {
    var num = 10;
    window.num = num;
})();
console.log(num);

三、示例说明

上面是这三种方式各自的一些特点,最后将其中重要的点通过一些小案例来看一看:

1、var变量提升/let,const临时死区

var定义变量,有变量提升,只提升变量声明,不提升变量赋值

console.log(a);			//undefined
var a = 5;
console.log(a);			//5

这段代码相当于:

var a;
console.log(a);			//undefined
a = 5;
console.log(a)			//5

如果是let/const进行定义之前访问变量(在临时死区),则控制台直接就会报错.

console.log(a);			//报错:Uncaught ReferenceError
//这里之前都是临时死区
let a = 5;
console.log(a)			//5
console.log(NUM);			//报错:Uncaught ReferenceError
//这里之前都是临时死区
const NUM = 5;
console.log(NUM)			//5

2、let/const形成块级作用域

for (let i= 1;i<5;i++) {
 	console.log(i)      //1,2,3,4,5
}
 console.log(i);         //报错:str is not defined

let定义变量使得for循环形成一个块级作用域,外部无法访问内部变量.

for (var j = 1; j < 5; j++) {
    const NUM = 8;
    console.log(j);      //1,2,3,4
}
console.log(j);         //5 var定义的变量可以在外部访问
console.log(NUM);       //报错:NUM is not defined	const定义的无法访问

var定义的变量外部可以直接进行访问,而const定义的变量使得for循环形成一个块级作用域,外部无法访问内部变量,直接报错.

3、let/const形成的块级作用域形成闭包

for (let i = 0; i < 4; i++) {
     (function fn() {
        console.log(i)          //0,1,2,3
    })()
}
console.log(i);     //报错 i is not defined

let声明变量i使得for循环变成了一个块级的作用域,类似于函数作用域,使得内部的函数形成了一个闭包函数.

4、const定义常量和对象、数组、函数、引用数据类型

4.1、const定义常量

// const NUM = 2;
 // NUM = 3;            //直接报错 Assignment to constant variable.

const定义常量的时候不能进行修改,否则控制台直接就会报错.

4.2、const定义对象、数组、函数、引用数据类型

const NUM = {
            name:'Tom',
            age:18,
            sex:"男"
        };
NUM.name = "Jary";			//修改内部变量
console.log(NUM);       //{name: "Jary", age: 18, sex: "男"}

当const定义常量对象、数组、函数、引用数据类型的时候,可以进行内部数据的修改