小白也能看得懂的JS基础之var let const的使用
var
在js中,万物皆可var
当你需要声明一个数字,字符串,布尔值甚至是数组或者对象的时候你都可以
// 用var声明数字,字符串,布尔值,数组,对象
var num = 1;
var str = 'Hello World';
var bool = true;
var arr = [];
var obj = { name: 'hulh', age: 23, gender: 'male' };
基本上,你可以用var声明所有的数据类型
使用var声明变量的时候,你可以不用初始化值,只是声明。此时所声明变量的值为undefined。
var name;
console.log(name); // undefined
但是,我们还是建议:尽量在声明变量的时候给它指定一个初始值,以免发生不可预知的错误。
使用var声明变量,你还可以重复声明同一变量,因为Javascript是逐行编译,因此后面声明的同名变量会覆盖前者。
var name = 'hlh';
console.log(name); // hulh
var name = 'HLH';
console.log(name); // HLH (不会报错)
此外,用var声明变量,会发生“变量提升”的现象,何为变量提升呢?通俗点说就是,你可以在定义这个值之前去使用它。
console.log(name); // 不会报错,而是会输出undefined(当然,仅限非严格模式下)
var name = 'hulh';
为何会发生这个现象呢?是因为Javascript编译器会在编译时会将所有的声明提升到作用域的顶部,所以上述代码看起来就像是下面这样:
var name;
console.log(name); // 不会报错,而是会输出undefined(当然,仅限非严格模式下)
name = 'hulh';
Javascript中有全局变量和局部变量,用var声明的变量,在浏览器环境中默认会挂载到window对象下,成为window对象的一个属性。
而当不使用var声明变量的时候,在浏览器环境中也会自动挂载到window对象下(相当于声明了一个全局变量,容易污染全局变量)。
let
let的作用与var差不多,但有一些区别:
let 声明的范围是块级作用域(ES6中新增了块级作用域),块级作用域由最近的一对大括号界定{},而 var 的声明范围是函数作用域
因此而发生的改变有:
// var
if (1) {
var name = 'hlh';
}
console.log(name); // hlh
// let
if (1) {
let name = 'hlh';
}
console.log(name); // 报错 name is not defined
let 声明的变量会形成暂时性死区,在这个块作用域内用 let 声明的变量,都不可以再重复声明,也不能在声明之前使用。
严格来讲,其实使用 let 声明的变量也会存在“变量提升”现象,但是因为暂时性死区的缘故,“变量提升”现象能够比较好的避免。
从某种角度来说,var 和 let 的“变量提升”是不一样的。
// 不能在声明之前使用
console.log(name); // 报错
let name = 'hlh';
// 不能重复声明
let name = 'HLH'; // Uncaught SyntaxError: Identifier 'name' has already been declared
在浏览器环境下,使用let声明的变量不会挂载到window上成为window的属性,避免了全局变量的污染。
const
var和let用于定义变量,即可变的量
而 const 用于定义常量,即不可变的量
用 const 定义的常量是只读的,无法修改
一个很经典的例子:
/*
* 我们都知道圆的面积计算公式是 S = π * r * r
* π 是一个永恒不变的值,假如我们用 var 或者 let
* 去声明的话,这个值就可能会意外的被改变
* 此时我们用 const 去声明,就可以避免值被改变
*/
let PI = 3.1415926;
PI = 3.1233333; // 不可
const PI = 3.1415926;
PI = 3.1233333; // Uncaught TypeError: Assignment to constant variable.
使用 const 声明常量,一旦声明就必须赋值,否则会报错
const PI; // Uncaught SyntaxError: Missing initializer in const declaration
const 声明的常量与 let 声明的变量一样,同样存在暂时性死区,声明的范围也是块级作用域,同样不可重复声明
// 暂时性死区
console.log(PI); // ReferenceError: Cannot access 'PI' before initialization
const PI = 3.1415926;
// 块级作用域范围
if (1) {
const PI = 3.1415926;
console.log(PI); // 3.1415926
}
console.log(PI); // ReferenceError: PI is not defined
// 不可重复声明
const PI = 3.1415926;
const PI = 3.14; // SyntaxError: Identifier 'PI' has already been declared
也许有些人会问,当我用 const 声明对象的时候,为什么对象的属性可以被改变?
大家都知道,声明对象时,javascript编译器会在堆内存中开辟出一块地址用以存放该对象,而 const 定义的常量存放的只是该对象的地址指针而已,只要地址指针没有改变,就没有违背不可改变的原则
我们修改对象的属性时,操作的是堆内存中的对象,并非 const 定义的这个常量本身,假如我们修改了这个常量的值,才会报错
更详细的解释可以参见:ECMAScript6入门(阮一峰) let和const命令 const 本质
const obj = {
name: 'hlh',
age: 23,
};
console.log('before', obj);
obj.name = 'HLH'; // 不会报错
console.log('after', obj);
/**
* if we change the constant obj,
* we actually modify the address of the obj.
*/
obj = {
name: 'HuLiehao',
age: 23,
gender: 'male',
}; // Uncaught TypeError: Assignment to constant variable.
综上所述
我们在声明变量时应该优先使用 let ,定义常量则使用 const
以上
仅为本人拙见,如有错误或遗漏,请不吝赐教