Object.defineproperty(obj, prop, desc )
- obj 需要定义属性的当前对象
- prop 当前需要定义的属性名
- desc 描述符 一般是一个对象
Object.defineproperty 的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性。
desc对象 :
value: 设置属性的值
writable: 值是否可以重写。true | false。 默认为false。
enumerable: 目标属性是否可以被枚举。true | false。 默认为false。
configurable: 目标属性是否可以被删除或是否可以再次修改特性。true | false。 默认为false。
get:属性的 getter 函数,如果没有 getter,则为 `undefined`。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 `this` 对象(由于继承关系,这里的`this`并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。 **默认为 `undefined`** 。
set:属性的 setter 函数,如果没有 setter,则为 `undefined`。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 `this` 对象。 **默认为 `undefined`** 。
当使用了get或set方法时,不允许使用writable和value这两个属性。其他属性值默认为false。get或set不是必须成对出现,任写其一就可以。
例1:
testHandle() {
let user = { name: '蜗牛' }
let conunt = 20
Object.defineProperty(user, 'age', {
get() {
console.log("这个人来获取值了!!");
return conunt
},
set() {
console.log("这个人来设置值了!!");
conunt = conunt+1
}
})
console.log(user) //注意。此时打印的是user
user.age = 100
console.log(user)
},
打印结果:
{name:'蜗牛',age:21}
这个人来设置值了!!
{name:'蜗牛',age:21}
- 此时,我有个疑问🤔️,为什么第一次打印的x时候不是20呢。我是先打印后赋值呀。如果我对赋值操作,延迟执行,就是先20,后21。
- 解答一下:其实也不是20。这个地方对象进行了引用,点开时候,给了我最新的值。使用JSON剥离打印,第一次打印时是没有age属性的。这样子就对啦。🫡
let user = { name: '蜗牛' }
let count = 20
Object.defineProperty(user, 'age', {
get() {
console.log("这个人来获取值了!!");
return count
},
set() {
console.log("这个人来设置值了!!");
count = count+1
}
})
console.log(JSON.parse(JSON.stringify(user)))
user.age = 'hahhahah'
console.log(user)
打印结果:
{name:'蜗牛'}
这个人来设置值了!!
{name:'蜗牛',age:21}
testHandle() {
let user = { name: '蜗牛' }
let conunt = 20
Object.defineProperty(user, 'age', {
get() {
console.log("这个人来获取值了!!");
return conunt
},
set() {
console.log("这个人来设置值了!!");
conunt = conunt+1
}
})
console.log(user.age) //注意。此时打印的user.age
user.age = 100
console.log(user.age)
},
打印结果:
这个人来获取值了!!
20
这个人来设置值了!!
这个人来获取值了!!
21
get和set方法,是当获取或设置属性时,会调用函数。获取该属性的对象,并不会进入get函数
Object.defineproperties(obj,props)
- obj 在其上定义或修改属性的对象。
- props 要定义其可枚举属性或修改的属性描述符的对象。
其他规则同上
var obj = {};
Object.defineProperties(obj, {
'age': {
value:"1",
writable:true,
get:function(){
return 1;
}
}
});
注意:不要在 get()/set() 方法中做如下操作,否则会造成死循环。
/*不要在get()/set() 方法中对 age 键做如下几种操作,否则会死循环:
1) this.age
2) this.age = 任何数字
3) return this.age
注:其他 键 也一样的
*/
var obj = {};
Object.defineProperties(obj, {
'age': {
get:function(){
/*不要在get方法中对 age 键做如下几种操作,否则会死循环:
1) this.age
2) this.age = 任何数字
3) return this.age
*/
console.log("哦豁,死循环了吧!")
return this.age
},
set:function(val){
/*不要在set方法中对 age 键做如下几种操作,否则会死循环:
1) this.age
2) this.age = 任何数字
3) return this.age
*/
}
}
});
console.log(obj.age);
和普通赋值的区别
一般通过为对象的属性赋值的情况下,对象的属性可以修改也可以删除,但是通过Object.defineProperty()或defineProperties定义属性,通过描述符的设置可以进行更精准的控制对象属性。