简单的理解 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 ...
随机推荐
- 修改eclipse中注释字体而不影响代码字体
eclipse的注释字体大小如何修改?不改变代码的字体 貌似没有直接的办法,但是可以取个巧: Window --> Preferences --> General --> Appea ...
- [luogu5577]算力训练
(以下以$B$为进制,$m$为幂次,$n=B^{m}$) 定义$\oplus$为$k$进制下不进位加法,$\otimes$为$\oplus$卷积 令$f_{i,j}$表示前$i$个数的$\oplus$ ...
- [noi34]palindrome
分割实际上就是不断地从两端取出一样的一段,并对剩下的串进行分割.下面我们来证明一下每一次贪心取出最短一段的正确性: 考虑两种分割方式,分别表示成S=A+B+A和S=C+D+C,其中A就是最短的一段,那 ...
- [cf643G]Choosing Ads
首先对于$p>50$,有经典的做法,即不断删去区间中不同的两数,最终剩下的即为出现次数超过一半的数(或没有),用线段树维护即可 那么对于$p\le 50$,类似的,即删去区间中不同的$\lflo ...
- [nowcoder5669A]Ancient Distance
对于一个$k$,可以二分枚举答案并判断,判断过程可以贪心找最深的点(线段树区间max)+倍增+线段树区间覆盖(清0)来实现,时间复杂度$o(klog_{2}n)$ 考虑反过来,暴力枚举答案$x$并求出 ...
- [bzoj1635]最高的牛
初始如果没有限制,很显然每一头牛高度都是h当只有一个限制,让h[a]到h[b]的高度都减1即可容易发现两个限制不会相交(否则必然矛盾),只会包含或相离,因此没有影响,直接差分/线段树即可(注意:1.不 ...
- 论文翻译:2020_WaveCRN: An efficient convolutional recurrent neural network for end-to-end speech enhancement
论文地址:用于端到端语音增强的卷积递归神经网络 论文代码:https://github.com/aleXiehta/WaveCRN 引用格式:Hsieh T A, Wang H M, Lu X, et ...
- hdu 5552 Bus Routes
hdu 5552 Bus Routes 考虑有环的图不方便,可以考虑无环连通图的数量,然后用连通图的数量减去就好了. 无环连通图的个数就是树的个数,又 prufer 序我们知道是 $ n^{n-2} ...
- Atcoder Grand Contest 054 题解
那天晚上由于毕业晚会与同学吃饭喝酒没打 AGC,第二天稍微补了下题,目前补到了 E,显然 AGC 的 F 对于我来说都是不可做题就没补了(bushi A 简单题,不难发现如果我们通过三次及以上的操作将 ...
- O(1)判断两点之间是否有边
O(1)判断两点之间是否有边 问题描述 给定一张 \(n\) 个点,\(m\) 条边的有向图. 多次询问,要求每次 \(\mathcal{O}(1)\) 判断两点之间是否有边(你可以忽略输入.输出等问 ...