ES6 Object.freeze与Object.seal详解:从基础用法到Vue性能优化

作者:南栀时间:2026-10-26 09:05:14浏览:520

本文深入解析ES6中Object.freeze与Object.seal的核心用法。Object.freeze实现对象浅冻结,禁止增删改属性;Object.seal允许修改值但禁止增删属性。文章对比了const与freeze的区别,并展示如何利用Object.freeze消除Vue2中大量静态数据的响应式开销以提升性能。此外,还通过递归结合Object.seal实现了深冻结对象的方法,适用于前端面试与复杂数据处理场景。

引言

随着ES6语法的持续演进,前端开发中涌现出大量实用的API工具。本文将重点介绍两个备受关注的对象处理API:Object.freeze和Object.seal。它们在实际开发中能带来哪些显著优势?其核心作用可以用“强大”二字概括。

Object.freeze

1.基本使用

从字面含义来看,freeze意为“冻结”,该API的作用正是对JavaScript对象进行冻结处理。接下来我们参考MDN(Mozilla开发者网络)的官方文档说明。

MDN官方解释

Object.freeze() 该方法用于冻结一个对象。被冻结的对象不可修改:无法添加新属性,无法删除现有属性,无法更改已有属性的可枚举性、可配置性、可写性,也无法修改已有属性的值。

官方解释虽然严谨但略显晦涩,其核心含义可以简化为:Object.freeze使对象变为只读状态,禁止添加新属性、删除已有属性或修改任何现有属性的值。

功能演示

经过Object.freeze处理的对象,执行删除、添加或修改操作均无效。在非严格模式下,这些操作不会抛出错误,但也不会产生实际效果。

let obj = {name:"dzp",age:22}
Object.freeze(obj)
obj.name = "dzp2"//修改无效
delete obj.age//删除无效
obj.a = 1//添加无效
console.log(obj)// {name:"dzp",age:22}

拓展

读者可能会问,数组是否也能被冻结?在JavaScript中,数组本质上是对象的一种特殊形式,因此同样可以被冻结。冻结后的数组也表现为只读状态。

let arr = [1]
Object.freeze(arr)
arr[0] = 2//无效
arr.push(2)//无效
arr.shift()//无效
console.log(arr)//[1]

2.Object.freeze与const对比

提到freeze,许多人会联想到const关键字。两者虽都带有“冻结”的意味,但设计初衷和功能表现存在显著差异。

const通常用于声明普通变量,其值不可重新赋值。当const用于定义对象时,它锁定的是对象的内存地址,而对象内部的属性值依然可以被修改。

const定义普通变量

const a = 10
a = 20//error,报错无法修改

const定义对象

 const obj = {a:1}
 obj.a = 2//ok
 obj = {}//error,报错,不能修改地址

二者对比总结

  • const主要用于定义普通变量,而Object.freeze主要用于处理对象。
  • 使用const定义普通变量时,其值不可修改;定义对象时,仅锁定对象引用地址,内部属性仍可自由变更。
  • Object.freeze修饰的对象整体变为只读,任何增删改操作均无效。
  • 注意:Object.freeze修饰的对象仍可被重新赋值(改变地址),但一旦改变地址,原对象将失去冻结保护,这种操作在实际开发中通常没有意义。

3.常用功能

下面简要列举Object.freeze在实际开发中的几个典型应用场景。

  • 冻结目标对象(默认是浅冻结)
  • vue2中数据的性能优化

功能一:冻结目标对象

或许有人会觉得,冻结对象是显而易见的概念,为何还要单独讲解?请耐心阅读后续内容,我将详细阐述其深层含义。

Object.freeze默认执行的是浅冻结,而非深度冻结。在实际业务中,我们往往希望整个对象树完全只读,而单纯使用Object.freeze无法实现深层嵌套对象的完全冻结。

浅冻结示例

let obj = {name:"dzp",a:{b:1}}
Object.freeze(obj)
obj.name = "dzp2"//无法修改
obj.a.b = 2//可以修改
console.log(obj)//{name:"dzp",a:{b:2}}

从上述结果可以看出,freeze仅对对象的第一层属性生效。当对象层级大于等于2时,深层属性的冻结失效。这就是所谓的“浅冻结”,其原理类似于React函数组件中利用memo进行浅比较优化的设计思路。

深度冻结对象

既然Object.freeze只能进行浅冻结,无法真正冻结多层嵌套对象,我们需要自行设计深冻结逻辑。如下示例中涉及了Object.seal,建议先阅读后续关于Object.seal的介绍,再回过头理解深冻结的实现。(Object.seal将在后文详细讲解)

功能二:vue2数据优化

Object.freeze如何优化Vue2的数据性能?我们知道,Vue2中的data数据通过Object.defineProperty实现响应式监听,这会消耗一定的系统性能。如果接口返回的数据仅用于展示且数据量较大,对其进行响应式监听显然是不必要的。然而,Vue2默认将所有渲染数据视为响应式,如何利用Object.freeze消除这种不必要的响应式监听?答案正是Object.freeze。

<template>
  <div id="app">
    <div v-for="item in list" :key=item>{{item}}</div>
    <div @click="changeData()">修改数据</div>
  </div>
</template>
<script>
export default {
  name: 'App',
  data() {
    return {
      list:[]
    }
  },
  mounted(){
    //模拟接口获取数据
    setTimeout(() => {
      this.list.push(...[1,2,3,4,5])
      //将数据取消响应式
      Object.freeze(this.list)
    }, 2000);
  },
  methods:{
    changeData () {
      this.list.push(6)
    }
  }
}
</script>

效果

引言

若未使用Object.freeze,数组元素会正常渲染(例如显示6个)。通过freeze处理,我们直接消除了数据的响应式监听,使数据仅能展示而无法修改,从而在一定程度上提升了页面渲染性能。

Object.seal

Object.seal的使用频率虽不及Object.freeze,但在某些特定场景下不可或缺,例如利用Object.seal模拟Object.freeze的浅层或深层对象监听。

1.基本使用

MDN介绍

Object.seal() 该方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。只要当前属性的值原本是可写的,其值仍可被修改。

简化官方解释:Object.seal修饰的对象禁止添加或删除属性,但允许读取和修改现有属性的值。

简单使用

let obj = {name:"dzp"}
Object.seal(obj)
obj.age = 22//无法添加
obj.name = "dzp2"//可以修改
delete obj.name//无法删除
console.log(obj)//{name:"dzp2"}

值得注意的是,Object.freeze和Object.seal均只作用于对象的第一层(浅控制),对于层级大于等于2的嵌套对象,它们无法直接控制深层属性。

let obj = {name:'dzp',a:{b:1}}
delete obj.a.b
console.log(obj)//{ name: 'dzp', a: {} }

2.模拟Object.freeze

模拟Object.freeze是一道经典的面试手写代码题。我们可以借助Object.seal轻松实现这一功能。整体设计思路清晰:首先使用seal禁止对象增加和删除属性,然后利用Object.defineProperty将现有属性设置为不可写。

function myFreeze(obj) {
  if(obj instanceof Object) {
    Object.seal(obj)
    for(let key in obj) {
      Object.defineProperty(obj,key,{
        writable:false
      })
    }
  }
}
let obj = {name:"dzp",a:{b:1}}
myFreeze(obj)
obj.name = "dzp2"//无效
delete obj.name//无效
obj.age = 22//无效
obj.a.b = 2//有效,只冻结第一层
console.log(obj)//{name:"dzp",a:{b:2}}

3.模拟Object.freeze,同时保证对象深冻结

在浅冻结的基础上,只需增加递归逻辑即可实现深度冻结。整体设计简洁明了,易于理解。

function myFreeze(obj) {
  if(obj instanceof Object) {
    Object.seal(obj)
    for(let key in obj) {
      Object.defineProperty(obj,key,{
        writable:false
      })
      myFreeze(obj[key])
    }
  }
}
let obj = {name:"dzp",a:{b:1}}
myFreeze(obj)
obj.name = "dzp2"//无效
delete obj.name//无效
obj.age = 22//无效
obj.a.b = 2//无效,深冻结了
console.log(obj)//{name:"dzp",a:{b:2}}

总结

至此,Object.freeze和Object.seal的核心用法已讲解完毕。

以上就是ES6新语法Object.freeze和Object.seal基本使用的详细内容,更多关于ES6语法Object.freeze Object.seal的资料请关注本站其它相关文章!

作者最新文章