1.在 const 和let推出 之前,js 使用var 声明变量,例如:
var a = 1 ;
a = 2 ;
console.log(a); // 2
a=function (){};
console.log(a) // function (){}
上述js 代码片段,按照从上向下执行 , 对同一个变量a, 声明先赋值数字给a ,最后又把函数表达式赋值给a, 后面的赋值操作覆盖前面的值。
大家可以再看下面的两段代码:
console.log(a); function b(){};
var a = 1; /* undefined */ var a =undefined;
console.log(b); /* function b(){} */ 伪代码=> console.log(a)
function b(){}; a= 1 ;
console.log(window.a) /* 1 */ console.log(b) ;
console.log(window.a)
这里就是变量提升起到的作用。我们在用var或者函数声明的方式定义一个变量时,这个变量的定义会提升当前作用域的最顶端,若全局声明还会挂载到window上。如上方的伪代码, 如果函数名也改为同变量名的,函数声明提升优先级高于变量声明, (上面左边代码 b 改为a可以试一下哦);
变量提升 ,会污染全局环境,如下代码, 不管condition 值是什么 ,value都会添加到全局环境。如果希望模拟块状作用域,es5 通常采用自执行函数 (function(){})();
var condition ; var condition ;
if (condition) { var value ;
var value = 1; 伪代码 => if(condition) {
} value = 1;
console.log(value) /* undefined*/ }
console.log(value)
为了对变量生命周期 以及作用域的,我们使用 ES6 中 let,const定义变量的时候,并不会发生声明提升,并且只在局部(块)作用域有效; let
1. 不存在变量提升, 声明前访问变量报错, 也即行业所说的, 存在暂时性死区;先声明再访问。
console.log(name);
const name ='Tom'; // Uncaught ReferenceError: Cannot access 'name' before initialization
2. 不能重复声明 ,let 可以先声明后赋值, const 声明后需要立即赋值 ;
let b = 1;
const b = 2 ; // Identifier 'b' has already been declared
const c // Missing initializer in const declaration
3. 存在块状作用域,const let 声明的全局变量不会挂载到顶层对象上 浏览器顶层对象window ,(node:global);
const f = 888;
console.log(window.f) // undefined
if(true){
const d = 555;
let e =333;
}
console.log(d); // Uncaught ReferenceError: d is not defined
console.log(e); // 上方报错退出执行栈, 报错同上;
4. const 一旦声明,值不能改变, let声明的变量值可以改变;
const 具体表现,简单类型值不能改变;
引用类型的值,变量指向的指针不能变化,只能保证指针是固定的(总是指向同一个地址),它内部的值是可以改变的, 例如对象的属性, 或者数组(push
、shift
、splice
等方法改变内容);
简单类型:
const p = '不能改变';
p = '报错' //Uncaught TypeError: Assignment to constant variable.
引用类型:
const g = ['不能改动']
const g2 = {
name: 'OBKoro1'
}
g[0] = '不报错'
g2.name = '不报错'
g = ['报错']
g2 = {
name: '报错'
}
总结一下 :
var
和let
/const
的区别:
- 块级作用域
- 不存在变量提升
- 暂时性死区
- 不可重复声明
- let、const声明的全局变量不会挂在顶层对象下面
const
命令两个注意点:
-
let
可以先声明稍后再赋值,而const
在 声明之后必须马上赋值,否则会报错 -
const 简单类型一旦声明就不能再更改,复杂类型(数组、对象等)指针指向的地址不能更改,内部数据可以更改。
-
const 声明的变量对于维护者更友好,建议尽可能使用const