JavaScript 对象不变性介绍

目录
  • 1. 基本概念
  • 2. Object.freeze()
  • 3. Object.seal()
  • 4. const关键字?
  • 5. 总结

1. 基本概念

对象不变性在任何编程语言中都是一个重要的概念。它会限制对象修改并防止不需要的更改。简而言之,对象的不变性就是将它的状态变为只读的,下面就来看看在 JavaScript 中的对象不变性。​

JavaScript中,一个对象可以有一个或多个属性。每个属性都是一个键值对,

下面是一个对象:

const user = {
    name: 'CUGGZ',
  age: 24,
}

这里使用const关键字定义了一个对象,它具有两个属性。默认情况下,对象是可变的,也就是说,我们可以给对象添加新属性,修改现有属性或者删除已有属性。而在某些情况下,我们可能希望对象是不可变的,即不能添加新属性,也不能修改和删除已有属性。

2. Object.freeze()

顾名思义,freeze() 就是用来冻结对象的。只需要将不想被更改的对象传递给它,就会返回该对象的不可变版本:

const user = {
    name: 'CUGGZ',
  age: 24,
}

const freezeUser = Object.freeze(user);
freezeUser.age = 18;
console.log(freezeUser.age) // 24

这时,新的对象就不可变了,相当于被冻结了。​

JavaScript了,提供了一个Object.isFrozen(),它可以用来判断一个对象是否被冻结:

Object.isFrozen(user)  // false
Object.isFrozen(freezeUser)  // true

需要注意的是, Object.freeze() 方法不会影响嵌套对象,对于嵌套对象,冻结后仍然是可以操作的:

const user = {
    name: 'CUGGZ',
  age: 24,
  article: {
      title: 'learn javascript',
    number: 1234
  }
}

const freezeUser = Object.freeze(user);
freezeUser.age = 18
freezeUser.article.number = 666;
console.log(freezeUser.age)             // 24
console.log(freezeUser.article.number); // 666

可以看到,使用Object.freeze() 方法冻结的对象,age是不可以更改的,但是嵌套对象的number属性还是可以修改的。如果需要冻结嵌套对象使其不可变,就需要使用循递归来逐级冻结,下面是一个简单的递归冻结实现:

const deepFreeze = obj => {
  Object.keys(obj).forEach(prop => {
    if (typeof obj[prop] === 'object') {
        deepFreeze(obj[prop]);
    }
  });
  return Object.freeze(obj);
};

deepFreeze(user);

Object.freeze()方法除了可以用来冻结对象以外,还可以用于冻结数组,使其不可变:

const number = [1, 2, 3, 4, 5];
const freezeNumber = Object.freeze(number);
freezeNumber.push(6);

此时就会报错了:

VM210:3 Uncaught TypeError: Cannot add property 5, object is not extensible

3. Object.seal()

Object.seal() 顾名思义就是密封对象,它是另一种使对象不可变的方法。相对于freeze(),Object.seal() 方法仅保护对象不能添加和删除属性,它允许更新现有的属性。

const user = {
    name: 'CUGGZ',
  age: 24,
}

const sealUser = Object.seal(user);
sealUser.age = 18;
delete sealUser.name;
console.log(sealUser)   // {name: 'CUGGZ', age: 18}

可以看到,我们识图删除对象中的name属性,删除失败;而修改已有的age属性,修改成功。​

Object.seal()方法和Object.freeze()一样,对于嵌套的对象,是无法实现不可变的,如果想要实现,同样要使用递归来一层层来密封对象。​

JavaScript同样提供了一个Object.isSealed() 方法来确认对象的密封状态:

Object.isSealed(user)      // false
Object.isSealed(sealUser)  // true

4. const关键字?

你是否会认为,使用const关键字也能达到相同的结果呢?实际上,他们是不一样的,当我们使用const关键字来创建对象时,它会阻止我们重新分配值,但是我们可以更新、添加、删除已有对象的属性:

const user = {
    name: 'CUGGZ',
  age: 24,
}

delete user.age;
user.height = 180;
user.name = 'hello';
console.log(user);  // {name: 'hello', height: 180}

而如果我们给user重新赋值,那么就会报错了:

Uncaught TypeError: Assignment to constant variable.

因此,const关键字仅仅是提供了赋值的不变性,而不会提供值的不变性(对于对象来说)。

5. 总结

本文简单介绍了两种可以用于使JavaScript不可变的方法。简而言之,Object.seal()方法会阻止更新、删除和向对象添加新属性,Object.seal()只会阻止添加和删除属性。、

除此之外,JavaScript还提供了一个Object.preventExtensions()方法,该方法可以让一个对象变的不可扩展,也就是永远不能再添加新的属性。

const user = {
    name: 'CUGGZ',
  age: 24,
}

const newUser = Object.preventExtensions(user);
newUser.height = 180;
console.log(newUser);  //  {name: 'CUGGZ', age: 24}

最后来看看它们三个的对比:

方法/操作 读取 创建 更新 删除
Object.freeze()
Object.seal()
Object.preventExtensions()

到此这篇关于JavaScript 对象不变性介绍的文章就介绍到这了,更多相关JavaScript 对象不变性内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解JavaScript对象转原始值

    目录 Object.prototype.valueOf() Object.prototype.toString() Symbol.toPrimitive 对象转换原始值 1. 预期被转换成字符串类型 2. 预期被转换成数字类型 3. 预期被转换成默认类型(其他) 三种方法触发的顺序 总结 Object.prototype.valueOf() 对象的valueOf旨在返回对象的原始值,会在需要将对象转换成原始值的地方自动执行.详细点这里. Object.prototype.toString() t

  • js中常见的4种创建对象方式与优缺点

    目录 前言 1.工厂模式 2.构造函数模式 3.原型模式 4.Object.create() 其他模式 总结 前言 说起创建对象,最容易想到的便是通过对象字面量方式直接定义一个对象吧,但这种方式只能创建少量,单独且相互间无联系的对象.若要批量创建对象,该如何? 1.工厂模式 实现: function fn(a,b){ let obj = new Object() obj.a=a obj.b=b return obj } const test = fn(1,2) 优点:解决了创建多个类似对象的问题

  • JavaScript内置对象介绍

    目录 一.内置对象 二.Math对象 1.Math对象的使用 2.生成指定范围的随机数 三.日期对象 1.Date()方法的使用 2.日期对象的使用 3.获取时间戳 四.数组对象 1.数组对象的创建 2.检测是否为数组 3.添加删除数组元素的方法 4.数组排序 5. 数组索引方法 6.数组转换为字符串 五.字符串对象 1.根据字符返回位置 2. 根据位置返回字符 3. 字符串操作方法 4.split()方法 一.内置对象 内置对象就是指 JS 语言自带的一些对象,这些对象供开发者使用,并提供了一

  • JavaScript 对象不变性介绍

    目录 1. 基本概念 2. Object.freeze() 3. Object.seal() 4. const关键字? 5. 总结 1. 基本概念 对象不变性在任何编程语言中都是一个重要的概念.它会限制对象修改并防止不需要的更改.简而言之,对象的不变性就是将它的状态变为只读的,下面就来看看在 JavaScript 中的对象不变性.​ 在JavaScript中,一个对象可以有一个或多个属性.每个属性都是一个键值对, 下面是一个对象: const user = {     name: 'CUGGZ'

  • javascript Number 与 Math对象的介绍

    目录 一.javascript 中 Number 二.Javascript中Math对象 一.javascript 中 Number javascript 中,数值类型属于原始类型. 除了我们所知道的以十进制表示的普通数值外,还可以用 0x 表示 十六进制整数, 0b表示二进制整数, 0O表示八进制整数 0xa //对应十进制 10 0b101 //对应十进制 5 0o22 //对应十进制 18 在javascript,0可以当作除数,返回值是无穷大.这点和其它语言有很大的区别.例如python

  • JavaScript可迭代对象详细介绍

    目录 1.迭代器 2.迭代器接口与可迭代对象 3.自定义可迭代对象 3.1.可迭代的Range对象 3.2.使用Generator函数作为迭代器接口 3.3.可迭代的List 3.3.可迭代的迭代器 4.可迭代对象的意义 5.使用可迭代对象 6.后记 1.迭代器 迭代器是借鉴C++等语言的概念,迭代器的原理就像指针一样,它指向数据集合中的某个元素,你可以获取它指向的元素,也可以移动它以获取其它元素.迭代器类似于数组中下标的拓展,各种数据结构,如链表(List).集合(Set).映射(Map)都有

  • 目前流行的JavaScript库的介绍及对比

    为了简化JavaScript的开发,一些JavaScript程序库诞生了.JavaScript程序库封装了很多预定义的对象和使用函数,能帮助使用者轻松地建立有高难度交互的Web2.0特性的富客户端页面,并且兼容各大浏览器.下面是目前集中流行的JavaScript程序库的介绍和对比. Prototype Prototype是最早成型的JavaScript库之一,对JavaScript的内置对象(例如String对象.Array对象等)做了大量的扩展.现在还有很多项目使用Prototype.Prot

  • JavaScript对象封装的简单实现方法(3种方法)

    本文实例讲述了JavaScript对象封装的简单实现方法.分享给大家供大家参考,具体如下: Javascript在HTML中变得越来越强大,富客户端,HTML5中的WebGL等.但是我们书写Javascript的时候往往很随意,使用对象的封装是极好的.这里介绍Javascipt三种创建对象的方法. 1. 使用关键字new创建对象 function Person(name, age) { this.name = name; this.age = age; } var p = new Person(

  • 创建、调用JavaScript对象的方法集锦

    今天在做项目时,遇到了需要创建JavaScript对象的情况.所以Bing了一篇老外写的关于3种创建JavaScript对象的文章,看后跟着打了一遍代码.感觉方法挺好的,在这里与大家分享一下.   一.利用函数创建对象: 复制代码 代码如下: //定义对象 function Animal(type) {     this.name="";     this.type=type;    this.introduction=function(){          return "

  • JavaScript 对象详细整理总结

    Javascript 对象总结: JavaScript对象可以看作是属性的无序集合,每个属性就是一个键值对,可增可删. JavaScript中的所有事物都是对象:字符串.数字.数组.日期,等等. JavaScript对象除了可以保持自有的属性外,还可以从一个称为原型的对象继承属性.对象的方法通常是继承的属性.这种"原型式集成"是JavaScript的的核心特征. 1.创建对象 第一种:对象直接量表示法创建对象. 这是最简单的对象创建方式,对象直接量由若干key:value键值对属性组成

  • 详解JavaScript对象的深浅复制

    前言 从层次上来看,对象的复制可以简单地分为浅复制和深复制,顾名思义,浅复制是指只复制一层对象的属性,不会复制对象中的对象的属性,对象的深复制会复制对象中层层嵌套的对象的属性. 在复制对象时,除了要复制对象的属性外,还要兼顾到是否保留了对象的constructor属性,是否对每一种数据类型(JavaScript常见的数据类型有String,Number,Boolean,Data,RegExp,Array,Funtion,Object)都实现正确的复制.项目中,我们可以根据实际情况,决定需要实现什

  • JavaScript对象数组如何按指定属性和排序方向进行排序

    引子 在以数据为中心的信息系统中,以表格形式展示数据是在常见不过的方式了.对数据进行排序是必不可少的功能.排序可以分为按单个字段排序和按多个字段不同排序方向排序.单字段排序局限性较大,不能满足用户对数据的关注点变化的需求,而多字段排序就可以较好的弥补这个缺陷. 多字段排序,实现的方式从大的层面上可以分为后端实现和前端实现. 后端排序 后端实现排序可以在数据库层面实现或者在应用程序层面实现. 数据库层面实现多字段排序非常简单,使用SQL的排序指令"Order By"即可--Order B

  • 使用ajax操作 JavaScript 对象

    通过请求获取充分格式化的HTML虽然很方便,但这也意味着必须在传输文本内容的同时也 传输很多HTML标签.有时候,我们希望能够尽量少传输一些数据,然后马上处理这些数据.在 这种情况,我们希望取得能够通过JavaScript进行遍历的数据结构.           使用jQuery的选择符可以遍历和操作取得的HTML结构,但是还有一种JavaScript内置的数据 格式,既能减少数据传输量,也会减少编码量. 1.取得JSON 前面我们曾经看到过,JavaScript对象是由一些"键-值"

随机推荐