JavaScript声明变量的方式有三种:var、let、const(es6新增let和const关键词来声明变量).
一、var
var是我们初学js时经常使用的一种声明变量的方式.
- var可以进行变量提升(预解析),只提升变量声明,不提升变量赋值.
- var可以进行变量的重复定义(后定义的值会覆盖原先定义的值).
- var定义的变量,只有在function当中定义外部无法访问,其他比如在for,if,while内部定义的都可以在外部进行访问.
- var定义的变量的作用域是window,可以用"window.变量名"来进行调用(一般都会省略简写).
二、let (es6新增)
let是es6新增的一种定义变量的方式,开发当中大量会用到.
- let不能进行变量的提升,不能进行变量的重复定义,也不能定义其他(var,const)方式已经定义过得变量.
- let定义变量会有临时死区(在let变量未定义之前的区域都称作临时死区,即在这些区域当中不能够访问到let所声明的变量).
- let定义的变量会形成一个块级作用域,在for,if,while内部定义变量在外部无法进行访问.类似函数内部的变量,这也是形成闭包的一种方式.
- let定义的变量作用域属于global,所以不能用"window.变量名"来调用;而global不会暴露在全局当中,所以也无法通过"global.变量名"来调用.
三、const (es6新增)
const也是es6所新增的定义变量的方式,一般在定义常量的时候使用.
- const一般是用来定义常量(1,2,a,b…),一旦定义,不能修改.
- const声明变量必须赋值,否则直接报错.
- 开发中,我们约定俗成的将const定义的变量名全部大写.
- 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的相同点:
- 变量作用域都属于global,都有临时死区,都会形成块级作用域使外部无法访问.
- 都不能进行变量的提升,不能定义其他(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定义常量对象、数组、函数、引用数据类型的时候,可以进行内部数据的修改