简单的理解 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数组声明
初始赋值值:例:一个二维数组,有二个1维数组组成,每一个一维数组有3个元素int[][] a = { {1,2,3}, {4,5,6} } ;动态二维数组声明:例:一个二维数组,有二个1维数组组成,每 ...
- 论文解读(LLE)《Nonlinear Dimensionality Reduction by Locally Linear Embedding》and LLE
论文题目:<Nonlinear Dimensionality Reduction by Locally Linear Embedding > 发表时间:Science 2000 论文地址 ...
- Spark SQL知识点大全与实战
Spark SQL概述 1.什么是Spark SQL Spark SQL是Spark用于结构化数据(structured data)处理的Spark模块. 与基本的Spark RDD API不同,Sp ...
- [noi239]count
将每一个ai表示为$ai=ki\cdot m+ri$,即满足$m\sum ki+\sum ri=n$且$0<ri<m$枚举$S=\sum ri$(S范围是$k\le S\le k(m-1) ...
- SpringMVC---Json的使用
1.所需文件 2.pom中加入json <?xml version="1.0" encoding="UTF-8"?> <web-app xml ...
- layui的入门使用
1.如果使用单独的layui插件的话需要先引入jquery的插件,官方建议1.8+的版本. 2.引入后就能根据规则正常使用了.
- mabatis的mapper文件找不到-ssm升级maven常见问题
手里项目之前是普通ssm的,打算用业余时间升级一把. 1.首先,搭建好maven的ssm项目. 2.配置好jdk,tomcat环境,先启动. 3.启动没问题后将maven目录结构布置好后直接将原有项目 ...
- Ubuntu 18.04.5 LTS Ceph集群之 cephx 认证及使用普通用户挂载RBD和CephFS
1.cephx认证和授权 1.1 CephX认证机制 Ceph使用cephx协议对客户端进行身份认证: 1.每个MON都可以对客户端进行身份验正并分发密钥, 不存在单点故障和性能瓶颈 2. MON会返 ...
- 洛谷 P4437 [HNOI/AHOI2018]排列(贪心+堆,思维题)
题面传送门 开始 WA ycx 的遗产(bushi 首先可以将题目转化为图论模型:\(\forall i\) 连边 \(a_i\to i\),然后求图的一个拓扑序 \(b_1,b_2,\dots b_ ...
- 详细解析Thinkphp5.1源码执行入口文件index.php运行过程
详细解析Thinkphp5.1源码执行入口文件index.php运行过程 运行了public目录下的index.php文件后,tp的运行整个运行过程的解析 入口文件index.php代码如下: < ...