简单的理解 Object.defineProperty()
Object.defineProperty()的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性。
Object.defineProperty(obj,prop,descriptor)
obj 要在其定义属性的对象
prop 要定义或者修改的属性的名称
descriptor 将被定义或修改的属性描述符
通过Object.defineProperty()为对象定义属性,有两种形式,且不能混合使用,分别为数据描述符,存取描述符。
下面分别描述两者的区别:
数据描述符 -- 特有的两个属性(value,writable)
value 属性值
writable 是否可以改变属性的值。默认为false,不能改变。
- let obj = {}
- Object.defineProperty(obj, 'name', {
- value: 'jack',
- writable: false // 不能改变属性的值
- })
- obj.name = '123'
- console.log(obj)// {name: 'jack'}
- let obj = {}
- Object.defineProperty(obj, 'name', {
- value: 'jack',
- writable: true // 可以改变属性的值
- })
- obj.name = '123'
- console.log(obj)// {name: 123}
存取描述符 -- 是由一对 getter、setter 函数功能来描述的属性
get:一个给属性提供getter的方法,如果没有getter则为undefined。该方法返回值被用作属性值。默认为undefined。
set:一个给属性提供setter的方法,如果没有setter则为undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认值为undefined。
- let obj = {}
- let temp = null
- Object.defineProperty(obj, 'name', {
- get: function (val) {
- return temp
- // console.log("set方法被调用"+val);
- },
- set: function (val) {
- temp = val
- console.log("get方法被调用" + val);
- }
- })
- obj.name = 'chen'
- console.log(obj.name) //chen
数据描述符和存取描述都具有以下描述符:
configrable 描述属性是否配置,以及可否删除
enumerable 描述属性是否会出现在for in 或者 Object.keys()的遍历中
configrable
单独设置:configurable: false 不能删除属性、不能重新定义属性
单独设置:configurable: true 能删除属性
同时设置:configurable:true 和 writable:false 可以修改属性值
注意:通过赋值的形式,不可以修改,因为 writable为false
- let obj = {}
- Object.defineProperty(obj,'name',{
- value: 'chen',
- configurable: true,
- writable: false
- })
- Object.defineProperty(obj,'name',{
- value: 'rose'
- })
- //通过属性定义的形式可以修改name的属性值
- console.log(obj.name)
- //通过赋值的形式,不可以修改,因为 writable为false
- obj.name = 'JS'
- console.log(obj.name)// rose
同时设置:configurable:false 和 writable:true 可以修改属性值
注意:通过赋值的形式,可以修改,因为 writable为true
- let obj = {}
- Object.defineProperty(obj,'name',{
- value: 'chen',
- configurable: false,
- writable: true
- })
- Object.defineProperty(obj,'name',{
- value: 'rose'
- })
- //通过属性定义的形式可以修改name的属性值
- console.log(obj.name) // rose
- //通过赋值的形式,可以修改,因为 writable为 true
- obj.name = 'JS'
- console.log(obj.name)// JS
configurable 总结:
configurable: false 时,不能删除当前属性,且不能重新配置当前属性的描述符(可以把writable的状态由true改为false,而无法由false改为true),但是在writable: true的情况下,可以改变value的值
configurable: true时,可以删除当前属性,可以配置当前属性所有描述符。
enumerable 看如下代码
- let obj = {}
- Object.defineProperty(obj,'name',{
- value: 'chen',
- enumerable: false
- })
- obj.gender = 'HTML'
- Object.defineProperty(obj,'age',{
- value: '110',
- enumerable: true
- })
- console.log(Object.keys(obj)) //['gender', 'age']
- for (let i in obj) {
- console.log(i)// gender,age
- }
- console.log(obj.propertyIsEnumerable('name')) // false
- console.log(obj.propertyIsEnumerable('gender')) // true
- console.log(obj.propertyIsEnumerable('age')) // true
注意:下面代码的区别
- let obj = {}
- obj.gender = 'HTML' // 等价于下面的代码
- Object.defineProperty(obj,'gender',{ // 等于这里
- value: 'HTML',
- configurable: true,
- writable: true,
- enumerable:true
- })
- Object.defineProperty(obj,'age',{ // 等价于下面的代码
- value: '120'
- })
- Object.defineProperty(obj,'age',{ // 等于这里
- value: '120',
- configurable: false,
- writable: false,
- enumerable: false
- })
不变性
1、对象常量
结合writable: false 和 configurable: false 就可以创建一个真正的常量属性(不可修改,不可重新定义或者删除)
- let obj = {}
- Object.defineProperty(obj,'name',{
- value: 'HTML',
- configurable: false,
- writable: false,
- })
- delete obj.name //不可删除
- obj.name = 'JS' //不可以重新赋值
- //通过赋值,可以添加新属性
- obj.gender = 'CSS'
- console.log(obj.gender) // CSS
- //不可重新定义
- Object.defineProperty(obj,'name',{value: 'chen'})// 报错: Cannot redefine property: name
2、禁止扩展
如果你想禁止一个对象添加新属性并且保留已有属性,就可以使用 Object.preventExtensions(...)
禁止扩展片段一:
- 'use strict'
- var obj = {name: 'JS'}
- Object.preventExtensions(obj)
- obj.gender = 'CSS'
- console.log(obj.gender) // Cannot add property gender, object is not extensible
禁止扩展片段二:
- var obj = {name: 'JS'}
- Object.preventExtensions(obj) // 禁止扩展
- // 但是仍然可以进行配置
- Object.defineProperty(obj, 'name',{
- value: 'HTML',
- writable: false,
- configurable: false
- })
- console.log(obj.name) // HTML
- //不能进行扩展
- obj.gender = 'CSS'
- console.log(obj.gender) //undefined
注意:在非严格模式下,创建属性gender会静默失败,在严格模式下,将会抛出异常。
3、密封
Object.seal()会创建一个密封的对象,这个方法实际上会在一个现有对象上调用object.preventExtensions(...)并把所有现有属性标记为configurable:false。
- var obj = {
- name: 'HTML'
- }
- Object.seal(obj)
- obj.gender = 'CSS'
- // 不能扩展属性
- console.log(obj.gender)// undefined
- // 再次验证
- console.log(Object.keys(obj)) // ['name']
- // 不能再次配置属性
- Object.defineProperty(obj,'name',{ // Cannot redefine property: name
- name: 'JS',
- configurable: true
- })
密封之后不仅不能添加新属性,也不能重新配置或者删除任何现有属性(虽然可以改属性的值)
4、冻结
Object.freeze()会创建一个冻结对象,这个方法实际上会在一个现有对象上调用Object.seal(),并把所有现有属性标记为writable: false,这样就无法修改它们的值。
- var obj = {
- name: 'HTML'
- }
- Object.freeze(obj)
- obj.name = 'Chen'
- // 不可以修改已有属性的值
- console.log(obj.name) // HTML
这个方法是可以应用在对象上级别最高的不可变性,它会禁止对于对象本身及其任意直接属性的修改(但是这个对象引用的其他对象是不受影响的)
你可以深度冻结一个对象,具体方法为,首先这个对象上调用Object.freeze()然后遍历它引用的所有对象,并在这些对象上调用Object.freeze()。
但是一定要小心,因为这么做有可能会无意中冻结其他共享对象。
- var obj = {
name: 'HTML'
}
Object.freeze(obj)
obj.name = 'Chen'
// 不可以修改已有属性的值
console.log(obj.name) // HTML
简单的理解 Object.defineProperty()的更多相关文章
- 深入理解 Object.defineProperty 及实现数据双向绑定
Object.defineProperty() 和 Proxy 对象,都可以用来对数据的劫持操作.何为数据劫持呢?就是在我们访问或者修改某个对象的某个属性的时候,通过一段代码进行拦截行为,然后进行额外 ...
- 理解 Object.defineProperty
理解 Object.defineProperty 本文写于 2020 年 10 月 13 日 Object.defineProperty 用于在一个对象上定义新的属性或修改现有属性并返回该对象. 什么 ...
- 理解Object.defineProperty()
理解Object.defineProperty() Object.defineProperty() 方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象. 基本语法:Obj ...
- 理解Object.defineProperty函数中的get与set
defineProperty是什么: 该函数可以直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象.通俗理解就是: 给对象添加一个新的属性,或者针对对象里的某些属性,可以给这 ...
- 理解Object.defineProperty的作用
对象是由多个名/值对组成的无序的集合.对象中每个属性对应任意类型的值.定义对象可以使用构造函数或字面量的形式: var obj = new Object; //obj = {} obj.name = ...
- [转] 理解Object.defineProperty的作用
对象是由多个名/值对组成的无序的集合.对象中每个属性对应任意类型的值.定义对象可以使用构造函数或字面量的形式: var obj = new Object; //obj = {} obj.name = ...
- 《转》理解Object.defineProperty的作用
对象是由多个名/值对组成的无序的集合.对象中每个属性对应任意类型的值.定义对象可以使用构造函数或字面量的形式: var obj = new Object; //obj = {} obj.name = ...
- vue之Object.defineProperty()
了解Object.defineProerty()方法 关于Object.defineProperty()方法的解释,理解Object.defineProperty的作用 这篇文章做了很详细的概述 关于 ...
- 20+行代码使用es5 Object.defineProperty 实现简单的watch功能
/** * 一个简单的demo 帮助理解defineProperty,只对Object类型参数有效 */ $watch=function(myObject,callback){ function in ...
随机推荐
- java动态编译——tools.jar问题
笔者在学习中写了一段简单的动态编译代码,但编译一直无法通过,起初认为受路径中存在汉字影响,修改路径后仍然没有解决.最终定位错误是:Java在进行动态编译的时候需要用到tools.jar资源包,若too ...
- lilypond 进阶—— 用scheme画图
lilypond的许多底层设定是通过scheme语言写的,特别是要写函数的时候. 所以了解一下scheme的作用很重要. 不幸的是,不像lilypond本身的代码,scheme代码的结果是不会直接预览 ...
- Swift-技巧(八)CVPixelBuffer To CGImage
摘要 Swift 中图像的表现形式不只是 Image,还有更加底层的方式,比如 CVPixelBuffer 像素缓存形式,那么像素缓存转换为可以在应用中展示的 CGImage,就要知道有哪些处理了. ...
- linux中为何每次修改完配置文件后都需要重新加载配置文件
1.大家刚接触linux时,可能会有这样的疑问:为什么每次修改完配置文件之后,总是要重新加载配置文件才能生效?或者需要重启后才能生效? 之前听过一个解释是这样子的: "修改了文件内容 ...
- 关于postman的接口登录验证问题
1.shiro的接口登录问题 碰到需要接口登录验证的:访问项目接口地址login,找到cookie将Cookie数据放入postman的headers 中. 2.碰到 security的项目.首先把相 ...
- [源码解析] PyTorch 分布式 Autograd (1) ---- 设计
[源码解析] PyTorch 分布式 Autograd (1) ---- 设计 目录 [源码解析] PyTorch 分布式 Autograd (1) ---- 设计 0x00 摘要 0x01 分布式R ...
- 【数据库】本地KEGG数据库如何拆分子库?
目录 KEGG本地库文件 按物种拆分KEGG数据库 1.获得物种分类信息 2.获得物种分类的序列信息并建库 3.获得物种分类的K-ko对应文件 根据相似性原理,序列相似,功能相似,所有功能注释无非是用 ...
- 【机器学习与R语言】4-决策树
目录 1.决策树原理 2.决策树应用示例 2.1)收集数据 2.2)探索和准备数据 2.3)训练模型 2.4)评估模型性能 2.5)提高模型性能 通过自适应增强算法(boosting) 将惩罚因子分配 ...
- 【Python小试】使用列表解析式简化代码
列表解析式的好处: 代码简洁 可读性强 运行快 示例 来自<Python编程>中的一个例子:同时投掷两颗面数不同的骰子(如一个6面的D6和一个10面的D10)n次,统计两个骰子点数之和,并 ...
- Linux中shell去除空行的几种方法
有时我们在处理和查看文件时,经常会有很多空行,为了美观或是有需要时,就有必要把这些除行去掉了,方法如下: #如需将结果输出加入重定向 > 文件名 1)用tr命令 代码如下: cat ...