let,const,var区别以及保持const不可修改

212 阅读2分钟

let,var区别

  1. let存在块级作用域,var不存在。
  2. var存在变量提升,let只有声明之后才能调用。
  3. var可以重复声明,let不能,会报错。
  4. let存在暂时性死区。 执行上下文环境中,var是在变量环境中的,let,const的声明是在词法环境里面(可以看一下执行上下文,更有助于理解这个)。

const

  1. 存在块级作用域,不能重复声明,存在暂时性死区。
  2. 只有声明之后才能调用,且声明之后必须赋值。
  3. 赋值后不能再修改。对于简单数据类型,修改会报错。对于引用数据类型,在没有修改地址的情况下,修改内容会成功。
const obj = {
name:"123"
}
obj.name = "456" //这种情况下是能修改成功的

如果对const定义的对象的属性也不能修改,可以根据下面的情况使用合适的方法

  1. Object.defineProperty()
//仅仅控制单个属性,对于新增,删除不能控制
Object.defineProperty(obj,"name",{writable:false})//通过writable设置属性不可更改
  1. Object.preventExtensions()
Object.preventExtensions(obj);//让对象变得不可扩展
obj.age = 22;
console.log(obj)//新的属性并没有添加上
Object.defineProperty(obj,"age",{value:22})//会报错
obj.__proto__.ceshi = "aaa"//在原型上添加属性
//但是这种方法可以修改和删除原有属性
obj.name = "66"
console.log(obj)
console.log(obj.ceshi)//'aaa' 在原型上添加属性成功
  1. Object.seal(): 相对于Object.preventExtensions()来说是多了禁止删除原有属性
  2. Object.freeze(): Object.freeze()方法会使被冻结的对象无法添加新的属性,无法删除旧属性,无法改变属性的值使得对象实际上变成了常量。(冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性)。
存在的问题:

2,3,4三种方法可以修改原型对象,来为对象添加属性。同时如果属性值是对象,只能冻结本身的对象,并不能冻结属性值的对象。 例如:

let obj1 = {
name:"aha",
like:["eat","sleep"]
}
Object.freeze(obj1)
obj1.like.push("play")
console.log(obj1)//此时会发现play已经添加到like里面了

手动编写一个冻结函数

function deepFreeze(obj){
  if(typeof obj !== "object"){
  throw Error("请传入正确对象")
}
Object.freeze(obj);
for(let key in obj){
  if(typeof obj[key] === "object"){
  //这里说明属性是对象
  deepFreeze(obj[key])
  }
}
}

let obj = {
name:"aha",
like:["eat","sleep"]
}
deepFreeze(obj)
obj.like.push("play")//会报错
obj.like[2] = "aaa" //会报错
obj.__proto__.ss = "aaa" //可以在原型上添加属性
console.log(obj)
console.log(obj.ss)