JS中的属性描述符

目录

什么是属性描述符

数据属性

存取器属性

get函数

set函数

存取器属性的应用

属性描述符总结


今天小编带大家了解一下js中的属性描述符

具体参考MDN官方文档:Object.defineProperty() - JavaScript | MDN (mozilla.org)icon-default.png?t=M85Bhttps://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

什么是属性描述符

属性描述符:它表达了一个属性的相关信息(元数据),本质上是一个对象

那了解属性描述符之前,先来了解几个关于属性的概念

数据属性

对于常规的对象创建的数据,全都是数据属性

举个例子

var obj = {
    x:1
}

obj.y = 2

对于上面obj对象的x属性或者添加的y属性就是数据属性

那么还有那些属性呢,接着往下看

存取器属性

- 当给它赋值时,会自动运行一个函数

- 当获取它的值时,会自动运行一个函数

举个例子,当给某个对象赋值时,会自动运行一个函数,读取它的值时也会运行一个函数,这就叫做存取器属性

var obj = {};

obj.x = 1;  //会自动运行一个函数
 
console.log(obj.x)  //会自动运行一个函数

那么怎么知道只是一个存取器属性,又或者说运行哪一个函数呢?

这时就需要我们的属性描述符来解决了

举个例子,如何将数据属性转换为存取器属性

var obj = {};

Object.defineProperty(obj,"x",{})  //这是一个方法

console.log(obj)

了解一下Object.defineProperty(),可以配置对象属性,其中可以传入三个参数,第一个为配置的对象名称,第二个为配置的属性名称,第三个为配置对象,里面可以写入属性描述符

如上图,当我第三个参数传入空对象时,x属性被创建了,但是值为undefined,当然也可也配置值,所对应的属性为value,例如将value的值赋值为1,这时候obj对于的x属性值就为1,相当于直接给obj.x = 1一样

 那么如何配置存取器属性呢?官方文档中给出如果配置了get和set属性的那就一定是存取器属性

举个例子

var obj = {};

Object.defineProperty(obj,"x",{
    get(){

    },
    set(){

    }
})

此时x属性就变成为存取器属性,但此时你会发现一个问题,当某个属性已经配置为存取器属性时,如果你再给它的value属性赋值,就会报错        

 

意思是,不能同时指定存取器和value值,两个不能同时赋值,这在官方文档中有描述

 

那么此时obj对象中有哪些属性呢?

 给大家了解一下obj中的get和set函数

get函数

get函数的作用:当读取配置属性时,将运行该函数,并且将该函数的返回值,作为读取属性的值

举个例子

var obj = {};

Object.defineProperty(obj,"x",{
    get(){
        console.log("x属性被读取了");  //输出x属性被读取了
        return 1;
    },
    set(){

    },
})

console.log(obj.x) //输出1

 上面执行obj.x,相当于调用了get函数,将函数的返回值输出了,因为这时候x已经被设置了存取器属性

set函数

了解了get之后,set相信大家也心里有数了

set函数的作用:当设置配置属性的值时,将运行该函数,并且将给该属性赋的值,作为函数的参数传入

举个例子给大家看看

var obj = {};

Object.defineProperty(obj,"x",{
    get(){
       
    },
    set(value){
        console.log("给x赋值了:" + value);  //输出给x赋值了:2
    },
})

obj.x = 2

 每一次对属性x赋值,都会运行set函数

了解完存取器属性,那到底对于开发者的意义在哪,接着往下看

存取器属性的应用

1.利用存取器属性来限制取值的范围

举个例子,假设这时需要一个用户对象,保存名字和年龄

function User(name,age){
    // 假设年龄范围为 0 ~ 150
    if (age > 150) {
        age = 150;
    }
    if(age < 0) {
        age = 0;
    }
    this.name = name;
    this.age = age;
}

var user = new User("name",18);
console.log(user);   // 输出User {name: 'name', age: 18}

这样看起来没啥毛病,但会有个隐患,如果你哪天将年龄重新修改了,但忘了年龄范围,这时就会出现下面的情况

function User(name,age){
    if (age > 150) {
        age = 150;
    }
    if(age < 0) {
        age = 0;
    }
    this.name = name;
    this.age = age;
}

var user = new User("name",18);

user.age = 1000;

console.log(user);  // 输出User {name: 'name', age: 1000}

很明显是不符合你的预期的,那么这时候就需要存取器属性来限制范围了

接着往下看

function User(name, age) {
    this.name = name;
    var _age
    Object.defineProperty(this, "age", {
        get() {
            return _age
        },
        set(value) {
            if (value < 0) {
                value = 0;
            } else if (value > 150) {
                value = 150;
            }
            _age = value;
        }
    })
    this.age = _age;
}

var user = new User("name", 18);

user.age = 1000;

console.log(user); 

这时候就完全没有隐患,因为每一次赋值后,都会运行set函数,在函数中判断是否需要修改

 介绍完存取器属性,接下来再给大家介绍其他的属性描述符

- configurable:当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。 默认为 false

- enumerable:当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。 默认为 false

- writable:当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符 (en-US)改变。 默认为 false

属性描述符总结

  • 拥有布尔值的键 configurableenumerable 和 writable 的默认值都是 false
  • 属性值和函数的键 valueget 和 set 字段的默认值为 undefined
  • 如果一个描述符不具有 valuewritableget 和 set 中的任意一个键,那么它将被认为是一个数据描述符。如果一个描述符同时拥有 value 或 writable 和 get 或 set 键,则会产生一个异常。

其实在平时的开发中,可能不习惯用属性描述符,但对于一些大工程,属性描述符是一个不错的选择,你学会了吗?

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JS && Lee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值