「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」。
介绍
var、let、const都是用于声明变量,在很多情况下var和let可以互相代替达到声明的变量预期效果。声明变量时语法都一样。
var
使用var声明的变量,一般情况下不是函数作用域就是全局作用域,它声明的变量没有块级作用域。 var声明的变量时能够变量提升,example如下
testVar();
function testVar(){
console.log(a);//undefined
var a = 1;
console.log(a);//1
}
由于javaScript引擎在代码预编译阶段会自动将代码内的var关键字声明的语句提升到当前作用域最上面。
var声明的变量可以挂载到window对象上
var c = 10;
console.log(window.c);//10
let
声明变量作用于块级作用域,只在当前作用域中有效。声明的变量不会挂载到window对象上,不允许重复定义变量,不存在变量提升(会报错)
let a = 10;
console.log(window.a);//undefined
testVar();
function testVar(){
//console.log(b);// Cannot access 'a' before initialization
let b = 1;
console.log(b);//1
}
const
用于声明常量,它声明的常数变量分两种情况,一个是简单数据类型的常量,数值是不能改变的;在声明的值是引用数据类型时,是变量的地址不能改变而不是值不能变。example如下:
//const obj = {name: 'zs',age: 20}
//console.log(obj); //{ name: 'zs', age: 20 }
const obj = {name: 'zs',age: 20}
obj.name = 'ls'
console.log(obj); //{ name: 'ls', age: 20 }
如何解决上述这种情况呢?一般情况下在单层对象结构时,可以使用Object.freeze()方法
const obj = {name: 'zs',age: 20}
Object.freeze(obj);
obj.name = 'ww'
console.log(obj); //{ name: 'zs', age: 20 }
当数据结构嵌套比较复杂时,就需要自己使用递归的方式做深层次冻结方法了,在这里简单实现了一下深层次冻结方法:
/**
* 深层次冻结复杂结构数据
* @param {*} obj
*/
function deepFreeze(obj){
Object.freeze(obj);
for(let key in obj){
// 判断key不属于原型链上的key
if(obj.hasOwnProperty(key)){
if(typeof obj[key] === 'object'){
deepFreeze(obj[key]);
}
}
}
}
const deepObj = {
name: 'zs',
age: 10,
like: {
foot: '香蕉'
}
}
Object.freeze(deepObj);
deepObj.like.foot = 'apple';
console.log(deepObj);//{ name: 'zs', age: 10, like: { foot: 'apple' } }
deepFreeze(deepObj);
deepObj.like.foot = 'apple';
console.log(deepObj);// { name: 'zs', age: 10, like: { foot: '香蕉' } }
区别
var和let/const区别
作用域问题: var没有块级作用域,有函数和全局作用域;let和const是块级作用域 挂载问题: var声明的变量,一般不指定挂载对象时,挂载在window对象上,而let和const不会挂载window对象上。
var c = 10;
console.log(window.c);//10
let a = 10;
console.log(window.a);//undefined
变量提升问题:var声明的变量,都会被提升到该作用域的最顶部;而let和const关键字声明的变量则不可以。 重复声明问题:var 支持同一个变量名可以多次声明;let和const声明的变量名不允许重复
let和const区别
let声明的变量可以改变,值和类型都可以改变;const声明的常量不可以改变