七个例子带你搞懂JS对象中的数据属性与访问器属性

简介: 有人会问:对象属性也分类别?!是指函数和变量的不同吗?还是分为可枚举属性或者是不可枚举属性,其实属性分为两个大类,一种为数据属性,一种为访问器属性

属性的类别

有人会问:对象属性也分类别?!是指函数和变量的不同吗?还是分为可枚举属性或者是不可枚举属性,其实属性分为两个大类,一种为数据属性,一种为访问器属性

数据属性

数据属性的作用如其名,起到存放数据的作用,比如描述对象的属性,对象的方法。而作为数据属性,其中有四个特性来描述数据属性的状态,分别为:ConfigurableEnumerableWritableValue,而我们可以通过Object.getOwnPropertyDescriptor()方法访问他们,除此之外还可以使用Object.defineProperty方法修改这四个特性。

let obj = {
  name: "猪痞恶霸",
  code: function () {
    console.log("猪痞恶霸最帅");
  },
};
Object.defineProperty(obj, "name", {
  value: "战场小包"
});
Object.getOwnPropertyDescriptor(obj, "name");
// {
//  configurable: true
//  enumerable: true
//  value: "战场小包"
//  writable: true
// }
obj.name // 战场小包
复制代码

在上面的代码中我们修改了描述属性的value特性并访问了描述属性的对象得到了包裹四个特性的对象,不难看出当我们修改value这个特性后对象的name值发生了改变,说明改变value属性,相当于间接改变相应属性的值。

Very Good!现在我们已经掌握了Object.getOwnPropertyDescriptor()Object.defineProperty,让我们带着这两个方法来探学习这四个特性的具体作用。

  • configurable:它控制了属性的可删除或者修改的状态,当值为true(默认为true)的时候我们可以修改或者删除属性的值,反之,我们将这个特性修改为false的时候,当前属性将无法进行删除或者重新定义。
let obj = {
  name: "猪痞恶霸",
  code: function () {
    console.log("猪痞恶霸最帅");
  },
};
Object.defineProperty(obj, "name", {
  configurable: false,
});
delete obj.name // false
obj
复制代码
  • 如上,我们将name属性的configurable状态更改为false,当我们使用selete关键字的时候,是无法删除的,返回false。这个时候有人问了,删除操作我知道,那么重新定义又是怎么一回事呢?其实无法重新定义就是我们无法再使用Object.defineProperty对这个属性进行修改了~
  • enumerable:可枚举的,这个概念很是熟悉,你想的没错,它控制属性是否可以被遍历到,默认为true,当值为true的时候,可以被遍历到,反之为ralse时则会在遍历的时候被忽略
let obj = {
  name: "猪痞恶霸",
  age:20,
};
Object.defineProperty(obj, "name", {
  enumerable: false,
});
for(item in obj) {
    console.log(item)
}
// age
复制代码
  • 我们将objname属性的enumerable可枚举描述设为false,不可枚举,使用for in遍历obj的时候跳过了name,所以只打印出了age
  • valuevalue在介绍修改与访问属性特性的方法部分提到过,它存储了属性值,当修改value值的时候,属性的值也会发生变化。
let obj = {
  name: "猪痞恶霸",
  code: function () {
    console.log("猪痞恶霸最帅");
  },
};
Object.defineProperty(obj, "code", {
  value:function() {
      console.log("猪痞恶霸最可爱");
  }
});
obj.code() // 猪痞恶霸最可爱
复制代码
  • 我带着好奇的心去尝试修改函数值,果不其然,函数值也可以被修改,因为其也是数据属性,只不过存储的是函数。
  • writable:控制着属性的值是否可以被修改。默认为true是可以被修改的,而当我们手动赋为false后将无法被修改
let obj = {
  name: "猪痞恶霸",
};
Object.defineProperty(obj, "name", {
  writable:false
});
obj.name = "Ned"
obj.name // 猪痞恶霸
复制代码
  • 看到结果后说明我们无法修改writable状态为false的属性

其实writableconfigurable的作用有些像冻结对象,Object.freezeObject.seal分别对应着writableconfigurable无法修改与无法删除,大家可以自己试一下。

访问器属性

访问器属性就是我们熟知的gettersetter存取器,我们可以通过绑定存取器来对对象属性读取或者修改操作进行拦截,在其中进行一些操作

let obj = {
    count:20,
    get counts() {
        console.log("get函数被调用")
        return this.count+10
    },
    set counts(value) {
        console.log("set函数被调用")
        this.count = value
    }
}
obj.counts // 30 get函数被调用
obj.counts = 100 // 100 set函数被调用
复制代码

上面的示例代码,在对象初始化的时候为其添加getset函数,当我们访问这些函数的时候,调用内部的代码,通过this来为对象的其他属性进行操作。

问题来了,如果我们在对象初始化之后想为其添加getset该怎么做呢?答案是使用Object.defineProperty方法

let obj = {
    _name:"猪痞恶霸"
}
Object.defineProperty(obj, "name", {
    get () {
        console.log("调用了get函数")
        return this._name
    },
    set (value) {
        console.log("调用了set函数")
        this._name = value
    }
})
obj.name // 调用了get函数
obj.name = "战场小包" // 调用了set函数 '战场小包'
复制代码

上面的例子是在我们初始化之后使用Object.defineProperty为其添加getset,传入目标对象,对外属性值以及保护getset函数的对象。


相关文章
|
5天前
|
Web App开发 JavaScript 前端开发
如何确保 Math 对象的方法在不同的 JavaScript 环境中具有一致的精度?
【10月更文挑战第29天】通过遵循标准和最佳实践、采用固定精度计算、进行全面的测试与验证、避免隐式类型转换以及持续关注和更新等方法,可以在很大程度上确保Math对象的方法在不同的JavaScript环境中具有一致的精度,从而提高代码的可靠性和可移植性。
|
1天前
|
JavaScript 前端开发
如何在 JavaScript 中使用 __proto__ 实现对象的继承?
使用`__proto__`实现对象继承时需要注意原型链的完整性和属性方法的正确继承,避免出现意外的行为和错误。同时,在现代JavaScript中,也可以使用`class`和`extends`关键字来实现更简洁和直观的继承语法,但理解基于`__proto__`的继承方式对于深入理解JavaScript的面向对象编程和原型链机制仍然具有重要意义。
|
10天前
|
监控 JavaScript 前端开发
确定使用 `defer` 属性还是 `async` 属性来异步加载 JavaScript
【10月更文挑战第24天】选择使用 `defer` 属性还是 `async` 属性来异步加载 JavaScript 是一个需要综合考虑多个因素的决策。需要根据脚本之间的依赖关系、页面加载性能要求、脚本的功能和重要性等因素来进行权衡。在实际应用中,需要通过测试和验证来确定最适合的加载方式,以提供更好的用户体验和页面性能。
|
6天前
|
前端开发 JavaScript
如何在 JavaScript 中访问和修改 CSS 变量?
【10月更文挑战第28天】通过以上方法,可以在JavaScript中灵活地访问和修改CSS变量,从而实现根据用户交互、页面状态等动态地改变页面样式,为网页添加更多的交互性和动态效果。在实际应用中,可以根据具体的需求和场景选择合适的方法来操作CSS变量。
|
5天前
|
JavaScript 前端开发 图形学
JavaScript 中 Math 对象常用方法
【10月更文挑战第29天】JavaScript中的Math对象提供了丰富多样的数学方法,涵盖了基本数学运算、幂运算、开方、随机数生成、极值获取以及三角函数等多个方面,为各种数学相关的计算和处理提供了强大的支持,是JavaScript编程中不可或缺的一部分。
|
9天前
|
数据采集 存储 JavaScript
如何使用Puppeteer和Node.js爬取大学招生数据:入门指南
本文介绍了如何使用Puppeteer和Node.js爬取大学招生数据,并通过代理IP提升爬取的稳定性和效率。Puppeteer作为一个强大的Node.js库,能够模拟真实浏览器访问,支持JavaScript渲染,适合复杂的爬取任务。文章详细讲解了安装Puppeteer、配置代理IP、实现爬虫代码的步骤,并提供了代码示例。此外,还给出了注意事项和优化建议,帮助读者高效地抓取和分析招生数据。
如何使用Puppeteer和Node.js爬取大学招生数据:入门指南
|
10天前
|
监控 JavaScript 前端开发
使用 `defer` 属性异步加载 JavaScript
【10月更文挑战第24天】使用 `defer` 属性异步加载 JavaScript 是一种有效的提高页面性能和用户体验的方法。通过合理设置 `defer` 属性,可以在不影响页面渲染的情况下异步加载脚本,并确保脚本的执行顺序。在实际应用中,需要根据具体情况选择合适的加载方式,并注意处理可能出现的问题,以确保页面能够正常加载和执行。
|
27天前
|
缓存 JavaScript 前端开发
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
29 1
|
23天前
|
JavaScript 前端开发 大数据
在JavaScript中,Object.assign()方法或展开语法(...)来合并对象,Object.freeze()方法来冻结对象,防止对象被修改
在JavaScript中,Object.assign()方法或展开语法(...)来合并对象,Object.freeze()方法来冻结对象,防止对象被修改
13 0
|
JavaScript 数据可视化 前端开发
《JavaScript数据可视化编程》——导读
在我们的日常生活中,数据的重要性与日俱增。尤其对于一些庞大的组织机构(诸如Facebook和Google这种体量的公司)来说,数据几乎是一切决策的核心。在地缘政治领域,正在前所未有地收集数据,以致爆出诸如美国国家安全局监控丑闻这样的事件,这从另一个侧面反映了我们正在经历一个宏观数据时代。
2831 0