let 与var对比 ,const简介

1.var 定义的变量 会进行变量提升:

       如果变量声明在函数里面,则将变量声明提升到函数的开头

       如果变量声明是一个全局变量,则将变量声明提升到全局作用域的开头

即只要定义了 即使在定义之前使用也不会报错 ,而let 定义的不会,在定义之前使用将会导致报错

console.log(k)
console.log(x)
let x = 10
var k = 'ddd'

console将打印

     undefined

     Uncaught ReferenceError: Cannot access 'x' before initialization

在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 锁定的是 堆和栈;

原文地址:https://www.cnblogs.com/xhliang/p/11971704.html