前言

现在有这样一个需求:用一个对象存储某学生的各科成绩,要求每次只能改变科目分数,不能再添加或者删除科目。

分析一下,这个需求其实就是需要创建一个固定属性的对象,其属性不可增删,但属性值可更改。

有些同学可能就这么开始了:

  • 首先,定义一个符合要求的对象:
  1. // 声明成绩存储对象
  2. let reportObj = {};
  3. // 给成绩存储对象添加科目,并设置科目属性不可增删,但科目成绩可修改
  4. Object.defineProperties(reportObj, {
  5. ChineseMark: {
  6. enumerable: true,
  7. writable: true,
  8. configurable: false,
  9. value: 60
  10. },
  11. EnglishMark: {
  12. enumerable: true,
  13. writable: true,
  14. configurable: false,
  15. value: 60
  16. }
  17. });
  • 然后写入成绩:
  1. // 存入科目成绩
  2. reportObj.ChineseMark = 99;
  3. reportObj.EnglishMark = 95;
  4. console.log(reportObj); // {ChineseMark: 99, EnglishMark: 95}

删除属性来试试:

  1. delete reportObj.ChineseMark; // false
  2. console.log(reportObj); // {ChineseMark: 99, EnglishMark: 95}

貌似确实符合条件了,那么再试试增加属性吧:

  1. reportObj.PhysicsMark = 100;
  2. console.log(reportObj); // {ChineseMark: 99, EnglishMark: 95, PhysicsMark: 100}

咋回事,怎么突然就不太符合要求了呢?Object.defineProperties() 只能精确控制所增添的属性的特质,但如果给对象添加属性的话,它就无力控制了。

今天我们就用简单的接口方法来实现一下这幺蛾子需求 ︿( ̄︶ ̄)︿

Object.seal()

描述

seal 如果作动词,那它的解释就是“密封”:

image-20210825210254120

见名知意,Object.seal() 方法就是用来“密封”一个对象的,它阻止对象添加新属性,并将对象所有的现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。

作用

通常,一个对象是可扩展的(可以添加新的属性)。

密封一个对象会让这个对象变的不能添加新属性,且所有已有属性会变的不可配置。属性不可配置的效果就是属性变的不可删除,以及一个数据属性不能被重新定义成为访问器属性,或者反之。但属性的值仍然可以修改。

尝试删除一个密封对象的属性或者将某个密封对象的属性从数据属性转换成访问器属性,结果会静默失败或抛出 TypeError(在严格模式 中最常见的,但不唯一)。

  1. const object1 = {
  2. property1: 42
  3. };
  4. Object.seal(object1);
  5. object1.property1 = 33;
  6. console.log(object1.property1);
  7. // expected output: 33
  8. delete object1.property1; // cannot delete when sealed
  9. console.log(object1.property1);
  10. // expected output: 33

总结起来,Object.seal() 其实就是做了以下事情:

  • 设置Object.preventExtension(),禁止添加新属性(绝对存在)
  • 设置configurable为false,禁止配置(绝对存在)
  • 禁止更改访问器属性(getter和setter)

语法

  1. Object.seal(obj)

参数

参数 obj 代表将要被密封的对象。

返回值

被密封的对象。

实现需求

既然有这么好用的方法,那我们当然要好好利用一番啦,终于可以完美实现文章开头的需求了:

  1. // 声明成绩存储对象及其属性
  2. let reportObj = {
  3. ChineseMark: 60,
  4. EnglishMark: 60
  5. };
  6. // 密封成绩对象
  7. let sealedReportObj = Object.seal(reportObj);
  8. // 更改科目分数
  9. sealedReportObj.ChineseMark = 99;
  10. sealedReportObj.EnglishMark = 97;
  11. console.log(sealedReportObj); // {"ChineseMark": 99, "EnglishMark": 97}

验证一下:

  1. // 增加属性
  2. sealedReportObj.PhysicsMark = 100;
  3. console.log(sealedReportObj); // {"ChineseMark": 99, "EnglishMark": 97}
  4. // 删除属性
  5. delete sealedReportObj.ChineseMark; // false
  6. console.log(sealedReportObj); // {"ChineseMark": 99, "EnglishMark": 97}

可以看到对象的属性确实是增删不了了,算是简单实现了需求吧。

扩展

如果要判断一个对象是否“密封”,我们可以使用 Object.isSealed() 方法:

  1. Object.isSealed(sealedReportObj); // true

Object.freeze()

看到这里,可能很多同学都想起了 Object.freeze() 方法,它的作用是用来冻结一个对象。实际作用就是字面意思:冻结一个对象,使其属性和属性值都不可更改。用来实现这个需求显然是不合适的。

共同点

Object.seal()Object.freeze() 有以下共同点:

  • 作用的对象变得不可扩展,这意味着不能再添加新属性。
  • 作用的对象中的每个元素都变得不可配置,这意味着不能删除属性。
  • 如果在 ‘use strict’ 模式下使用,这两个方法都可能抛出错误。

不同点

Object.seal() 能让你修改属性的值,但 Object.freeze() 不能。

总结

~

~本文完,感谢阅读!

~

学习有趣的知识,结识有趣的朋友,塑造有趣的灵魂!

大家好,我是〖编程三昧〗的作者 隐逸王,我的公众号是『编程三昧』,欢迎关注,希望大家多多指教!

你来,怀揣期望,我有墨香相迎! 你归,无论得失,唯以余韵相赠!

知识与技能并重,内力和外功兼修,理论和实践两手都要抓、两手都要硬!

参考文档:

Object.seal()

Object.freeze()

更多相关文章

  1. MVC架构模式,依赖注入,对象容器与门面技术
  2. 08-11 作业 面对对象和自动加载 封装 继承 多态
  3. php 重载与事件委托
  4. 判断是否为数组的 JavaScript 方法总结
  5. JavaScript语法综述
  6. 还在死磕 Ajax?那可就 out 了!
  7. 补:0811作业 类与对象
  8. OOP面向对象基本演绎
  9. opp基础:类与对象的 类的继承和调用 构造器 静态成员等

随机推荐

  1. 在C/C++中如何使用extern关键字
  2. c#中反射是什么?
  3. c++输出二维字符矩阵对齐
  4. C++实现逐行读取txt文件中的字符串以及文
  5. openjudge 2971:抓住那头牛 解题过程(附代
  6. C#学习之面向对象如何调用类以及普通方法
  7. Ruby和C ++之间的异同点是什么?
  8. .net中的重载是什么?
  9. C++ vector容器函数使用范例
  10. 【C语言】5种妙招教你轻松搞定变量值交换