属性描述符(get与set)

属性描述符

Property Descriptor 属性描述符 用于描述一个属性的相关信息 属性有哪些信息:目前知道的就只有两个一个是属性的名字,一个是属性的值; 其实属性还有其他的一些相关信息,比如这个属性能否在for-in循环中被循环出来,这个就叫做可枚举性,具体还有那些可以 通过Object.getOwnPropertyDescriptor(对象,属性名)可以得到一个对象的某个属性的属性描述符

const obj={
a:1,
b:2
}
const desc=Object.getOwnPropertyDescriptor(obj,'a')
console.log(desc)

 

由此可以看出属性描述符是一个对象

  • value:属性值
  • configurable:该属性的描述符是否可以修改
  • enumerable:该属性是否可以被枚举
  • writable: 该属性的值是否可以被重新赋值

Object.getOwnPropertyDescriptors(obj)可以得到某个对象的所有属性描述符

const obj={
    a:1,
    b:2
}
const allDesc= Object.getOwnPropertyDescriptors(obj)
console.log('allDesc',allDesc)

如果需要为某个对象添加属性时 或修改属性时,配置其属性描述符,可以使用下面的代码,一般情况下都是在对象中改或者直接obj.属性名=修改值; 下面代码则用不一样的方法修改值或者属性修饰符

const obj={
    a:1,
    b:2
}
//这里把属性的描述符变为不能修改
Object.defineProperty(obj,'a',{
    value:3,
    configurable:false,
})
const desc=Object.getOwnPropertyDescriptor(obj,'a')
console.log('desc',desc)

这里再次修改值和还原 configurable的值看看能不能修改属性修饰符

const obj={
    a:1,
    b:2
}
//这里把属性的描述符变为不能修改
Object.defineProperty(obj,'a',{
    value:3,
    configurable:false,
})
const desc=Object.getOwnPropertyDescriptor(obj,'a')
console.log('desc',desc)
Object.defineProperty(obj,'a',{
    value:4,
    configurable:true,
})
const desc2=Object.getOwnPropertyDescriptor(obj,'a')
console.log('desc',desc2)

这就说明你把configurable的值改为false后你就不能再进行属性修饰的修改了,这里注意:值可以修改的

修改enumerable的值

const obj={
    a:1,
    b:2
}

Object.defineProperty(obj,'a',{
    value:3,
    configurable:false,
    enumerable:false
})
const desc=Object.getOwnPropertyDescriptor(obj,'a')
console.log('desc',desc)
for (const prop in obj) {
console.log(prop)
}

是否可枚举可以看出把enumerable的值改为false,就不能遍历了,其中他还影响这个Object.keys()和Object.values()方法

const props=Object.keys(obj);
console.log(props);
const values=Object.values(obj);
console.log(values);

修改writable的值

const obj={
    a:1,
    b:2
}

Object.defineProperty(obj,'a',{
    value:3,
    configurable:false,
    enumerable:false,
    writable:false
})
const desc=Object.getOwnPropertyDescriptor(obj,'a')
console.log('desc',desc)
obj.a=10;
console.log(obj);

存取器属性

属性描述符总,如果配置了get和set中的任何一个,该属性,不再是一个普通属性,而变成了存取器属性

get和set配置均为函数,如果一个属性时存取器属性,则读取该属性时,会运行get方法,将get方法得到的返回值作为属性值;如果给该属性赋值,则会运行set

const obj={
    a:1,
    b:2
}
Object.defineProperty(obj,'a',{
    get(){
        console.log("运行了属性a的get函数")
    },
    set(val){
        console.log('运行了set方法', val)
    }
})
obj.a=10//运行了set方法
console.log(obj.a);//调用了get方法

为什么打印值为undefined?因为在调用obj.a的时候调用了get方法,但是get方法没有返回值所有就是undefined

哪下面运行结果打印的是什么

obj.a=obj.a+1相当于set(obj.a+1) set(get()+1)解析:先调用set方法,调用时发现参数里面有obj.a调用get方法 ,
调用get方法发现其返回值是undefined,undefined+1的值为NaN,虽然set函数计算的结果是NaN,但是最后调用get函数没有返回值结果还是undefined
obj.a=obj.a+1//相当于 set(obj.a+1) set(get()+1)
console.log(obj.a);//调用了get方法

想要把这个get和set做成一个正常的例子 有人就这样想,set函数中拿到obj.a然后把val的值赋给obj.a;然后再get函数中返回obj.a 如果这样做就会发现浏览器卡死进入无限递归,为什么会这样 当你再调用obj.a的时候就会运行get方法,然而get方法里面return的obj.a也相当于再调用get方法, 本来运行get方法需要算出值来,但是return obj.a相当于没等get算出来就又调用get方法所有就进行了无限递归;运行set方法也是一样的;所以使用存取器属性,千万不要再get里面去读取属性本身,再set里面也不要去设置属性本身

Object.defineProperty(obj,'a',{
    get(){
        console.log("运行了属性a的get函数");
        return obj.a
    },
    set(val){
        console.log('运行了set方法', val)
        obj.a=val
    }
})
console.log(obj.a);

那如何才能正确的拿到该属性呢

你可以给这个对象的别的属性赋值如obj._a=val,然后再get函数里面返回这个设置的属性 return obj._a这样就可以拿到和赋值了

Object.defineProperty(obj,'a',{
    get(){
        console.log("运行了属性a的get函数");
        return obj._a
    },
    set(val){
        console.log('运行了set方法', val)
        obj._a=val
    }
})
obj.a=10
console.log(obj.a);

存取器属性最大的意义,在于可以控制属性的读取和赋值

如下例子这样就可以控制年龄属性的值

let person={
    name:'wq',
}
Object.defineProperty(person,'age',{
    get(){
        return person._age
    },
    set(val){
        if(typeof val !=='number'){
            throw new TypeError('年龄必须是一个数字')
        }
        if(val>200){
            val=200;
        } else if(val<0){
            val=0
        }

        person._age=val
    }
})
person.age=-10
console.log(person.age);
person.age=1000
console.log(person.age);
person.age='213qref'
console.log(person.age);

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值