1.var 定义的变量 会进行变量提升:
如果变量声明在函数里面,则将变量声明提升到函数的开头
如果变量声明是一个全局变量,则将变量声明提升到全局作用域的开头
即只要定义了 即使在定义之前使用也不会报错 ,而let 定义的不会,在定义之前使用将会导致报错
console.log(k) console.log(x) let x = 10 var k = 'ddd'
console将打印
undefined
在ES6中 使用 LexicalEnvironment(词法环境) 来储存(let、const)
VariableEnvironment (变量环境) 组件存储(var),在 ES6 中,词法 环境和 变量 环境的区别在于前者用于存储**函数声明和变量( let
和 const
)绑定,而后者仅用于存储变量( var
)**绑定。
注 . JS中的变量提升正是变量环境引起的,在创建阶段函数声明被存储在环境中,变量被设置为undefined(由于创建阶段在执行阶段之前)所以var 声明的变量在声明之前就可以访问,其值为变量环境设置的undefined
详见:https://muyiy.cn/blog/1/1.1.html#%E5%88%9B%E5%BB%BA%E9%98%B6%E6%AE%B5
2.var 只有全局作用域和局部作用域之分,而let定义块级作用域
for (var j = 0; j < 10; j++) {
setTimeout(function() {
console.log(j)
})
}
// 10个10
// 下面可以正常访问 会污染全局变量
console.log('-------', j)
console.log('-------', window.j)
for (let i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i)
})
}
// 0---9分别被打印
// 下面报错Uncaught ReferenceError: i is not defined
console.log('-------', i)
注意:var 定义的全局变量会自动添加到window上作为对象的属性,就像js的全局函数可以通过window访问一样
在控制台打印window 可以展开看 j 是 10 被挂载到了window上
js的全局方法 escape(),eval(),isNan(),isFinite(),parseFloat(),parseInt(),unescape();都可以通过window访问,这样我们往往会将window的自身方法和js的全局方法混淆了
3. var 可以被重新定义和赋值而let不行 对let进行重新赋值将会报错
let x = 10 let foo = () => { console.log('------------', x) // 不能被重新定义 下面将会报错 let x = 20 x++ } // 不能被重新定义 下面将会报错 不论全局还是局部 let x = 1 foo()
var k = '444' var k = 'kjk' console.log(k) //可以正常输出
4 const 同let相同是块级作用域
const声明一个只读的常量,一旦声明,常量的值就不能改变,这意味着,const一旦声明常量,就必须立即初始化,不能等到之后再赋值。因此,改变常量和只声明不赋初始值都会报错。
const的作用域与let命令相同,只在声明所在的块级作用域内有效。
if (true) { const i = 1; } console.log(i); //报错
我们理解的是const定义的是常量,但是const定义对象是锁定的是对象的地址而不是本身对象的值,就对象属性可以被改变 ;const定义的对象做为形参时也会被修改内容;
const aaa = 1 const ttt = {k:111} ttt.k = 222 console.log(ttt) //{k:222} aaa = 3 //Uncaught TypeError: Assignment to constant variable.
注:当请整个对象都被锁定可以使用Object.freeze(),该方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,
不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。 freeze() 返回和传入的参数相同的对象。
var obj = { prop: 42 }; // 作为参数传递的对象与返回的对象都被冻结 // 所以不必保存返回的对象(因为两个对象全等) var oo = Object.freeze(obj); console.log(oo=== obj) //true // 添加属性将不做任何事情,严格模式下会报错; obj.pars = 1 // 修改属性 也不会器作用,严格模式下会报错; obj.prop = 33; console.log(obj); //42
可以理解为 const 锁定的是 栈,Object.freeze 锁定的是 堆和栈;