js--对象内部属性与 Object.defineProperty()
前言
JavaScript 中允许使用一些内部特性来描述属性的特征,本文来总结一下对象内部属性与 Object.defineProperty() 的相关知识。
正文
1、属性类型
js中使用某些内部属性来描述属性的特征,比如描述属性是否可以枚举,是否可以修改等特征,我们无法访直接问属性的这些特征,但是可以通过[[]]的方式来将某个特性标识为内部属性。这些内部属性分为数据属性和访问器属性。
(1)数据属性
数据属性包含一个保存数据值的位置。值会从这个位置读取,也会写入到这个位置。数据属性有 4个特性描述它们的行为。
a、[[Configurable]]表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把数据属性修改为访问器属性,默认 true。
b、[[Enumerable]]表示能否通过 for-in 循环遍历出属性 默认 true。
c、[[Writable]]表示能否修改属性的值,默认 true,设置为 false 指改属性只读。
d、[[Value]]保存这个属性的数据值,读写属性的值都是在这个位置,默认值为 undefined。
要修改对象默认数据属性,必须使用es5的 Object.defineProperty(),该方法包含三个参数,给其添加属性的对象、属性的名称和一个描述符对象。如下:
var person = {};
Object.defineProperty(person, "age", {
enumerable: true,
configurable: false,
value: 18
});
console.log(person.age);// 18
delete person.age
console.log(person.age);// 18
Object.defineProperty(person, "height", {
enumerable: false,
value: 50
});
console.log(person);//{age:18,height:50}
for (const key in person) {
console.log(key, person[key]);// age 18
}
Object.defineProperty(person, "name", {
writable: false,
value: "Nicholas"
});
console.log(person.name); // "Nicholas"
person.name = "Greg";
console.log(person.name); // "Nicholas"
注意:在调用 Object.defineProperty() 时, configurable 、 enumerable 和 writable 的值如果不指定,则都默认为 false 。
(2)访问器属性
访问器属性 ==访问器属性不包含数据值,他们包含setter和getter函数,这两个函数并不是必须的
a、[[Configurable]]表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把数据属性修改为访问器属性,默认 true。
b、[[Enumerable]]表示能否通过for-in循环遍历出属性 默认 true。
c、[[Set]]写入属性的函数,默认 undefined。
d、[[Get]]读取属性的函数,默认 undefined。
同样,访问器属性是不能直接定义的,必须使用 Object.defineProperty() 。如下:
var person = { name: "Nicholas", isAdult: true };
Object.defineProperty(person, 'age', {
get: function () {
return this.age
},
set: function (newValue) {
this.isAdult = newValue >= 18 ? true : false
}
});
console.log(person.isAdult);
person.age = 17
console.log(person.isAdult);
注意:设置了访问器属性之后不能再设置数据属性,比如设置了 set/get 就不能再设置 writable。
2、补充:内部属性的操作
(1)一次性定义多个属性
var person = {}
Object.defineProperties(person, {
'name': {
value: "Nicholas"
},
'isAdult': {
writable: true,
configurable: true,
value: true
},
'age': {
configurable: true,
get() {
return this.age
},
set(newValue) {
this.isAdult = newValue >= 18 ? true : false
}
}
})
console.log(person.isAdult);// true
person.age = 17// 首先到age的set方法,然后访问isAdult的writable属性并修改value值
console.log(person.isAdult);// false
(2)读取属性的特性 Object.getOwnPropertyDescriptor()获取传入对象给定属性的描述符。Object.getOwnPropertyDescriptors()获取给定对象的全部属性描述符。
var person = { name: "Nicholas", isAdult: true };
Object.defineProperty(person, 'age', {
get: function () {
return this.age
},
set: function (newValue) {
this.isAdult = newValue >= 18 ? true : false
}
});
var descriptor = Object.getOwnPropertyDescriptor(person, 'age')
console.log(descriptor);
//configurable: false
// enumerable: false
// get: ƒ ()
// set: ƒ (newValue)
console.log(Object.getOwnPropertyDescriptors(person));
// {name:{...},isAdult:{...},age:{...}}
3、对象内部特性和 Object.defineProperty() 应用
(1)手写实现 const
function myConst(key, value) {
window.key = value // 把要定义的key挂载到window下,并赋值value
Object.defineProperty(window, key, {
enumerable: false,
configurable: false,
get: function () {
return value
},
set: function (data) {
if (data !== value) { // 当要对当前属性进行赋值时,则抛出错误!
throw new TypeError('Assignment to constant variable.')
} else {
return value
}
}
})
}
myConst('a', 2)
console.log(a);
a = 3//报错 :Assignment to constant variable.
(2)手动实现每次访问一个属性时,值加一,使得a==1&&a==2&a==3成为可能
window.b = 0
Object.defineProperty(window, "a", {
get() {
this.b++
return this.b
},
set(value) {
this.b = value
}
})
if (a == 1 && a == 2 & a == 3) {
console.log("111");
}//111
写在最后
以上就是本文的全部内容,希望给读者带来些许的帮助和进步,方便的话点个关注,小白的成长之路会持续更新一些工作中常见的问题和技术点。

js--对象内部属性与 Object.defineProperty()的更多相关文章
- js对象的属性:数据(data)属性和访问器(accessor)属性
此文为转载,原文: 深入理解对象的数据属性与访问器属性 创建对象的方式有两种:第一种,通过new操作符后面跟Object构造函数,第二种,对象字面量方式.如下 var person = new Obj ...
- C#对象内部属性排序测试
构建对象: class SortGrid { int indexI; int indexJ; public SortGrid(int x, int y) { indexI = x; indexJ = ...
- js对象中属性调用.和[] 两种方式的区别
JS 调用属性一般有两种方法——点和中括号的方法. 标准格式是对象.属性(不带双引号),注意一点的是:js对象的属性,key标准是不用加引号的,加也可以,特别的情况必须加,如果key数字啊,表达式啊等 ...
- 对象内部属性[[Class]]
1.概述 所有的typeof返回值为‘object’的对象都包含一个内部属性[[Class]],我们将它可以看做内部的分类,而非传统面向对象意义的分类.这个属性无法直接访问,一般通过Object.pr ...
- JS对象中属性的增删改查
对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性 对象的分类: 1.内建对象 -在ES标准中定义的对象,在任何的ES的实现中都可以 ...
- js基础学习之-js对象的属性
Js属性 1. 设置属性 1) 对象. 2) 对象[‘属性名’] 3) GetAttribute函数 2. 获取属性 1) 变量=对象. 2) 变量=对象[‘属性名’] 3) GetAt ...
- js对象的属性问题
ES6之前js的对象的属性只能是字符串, <html> <head> <script type="text/javascript"> var a ...
- JS对象或属性的不变性
提到不变性,不得不提一个概念: 对象常量定义:结合可写性与可配置性可以创建一个真正的常量属性(不可修改.重定义.删除) 不变性可划分为以下几个等级: 1)禁止扩展:Object.preventExte ...
- js对象常用属性和方法:复制一个对象,获取一个对象的所有key和所有value的方法
记录对象的一些实用使用方法及属性 // Object.assign() 多个对象合并 key相同则后面的覆盖前面的 const target = { a: 1, b: 2 }; const sourc ...
随机推荐
- [Comet1173]最简单的题
称区间$[l,r]$的"信息"为其的答案和第一个.最后一个大于$x$的位置,显然通过$[l,mid]$和$[mid+1,r]$的信息可以$o(1)$合并得到$[l,r]$的信息 考 ...
- [loj6033]棋盘游戏
将棋盘黑白染色,即构成一张二分图 将状态用一张二分图$G$和一个点$x\in V$描述(分别为仍未被经过的点的导出子图和当前棋子所在位置),并称将要移动棋子的一方为先手 结论:先手必胜当且仅当$x$一 ...
- [cf1515G]Phoenix and Odometers
显然这条路径只能在$v_{i}$所在的强连通分量内部,不妨仅考虑这个强连通分量 对这个强连通分量dfs,得到一棵外向树(不妨以1为根) 考虑一条边$(u,v,l)$,由于强连通,总存在一条从$v$到$ ...
- [atARC119D]Grid Repainting 3
将每一行和每一列分别作为一个点,当第$i$行第$j$列的格子为红色时,将第$i$行与第$j$列连边 此时,考虑选择第$i$行的红色格子并将第$i$行的格子全部改成白色: 关于这一操作的条件,即需要第$ ...
- 理解ASP.NET Core - 过滤器(Filters)
注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 Filter概览 如果你是从ASP.NET一路走过来的,那么你一定对过滤器(Filter)不陌 ...
- R语言与医学统计图形-【23】ggplot2坐标系转换函数
ggplot2绘图系统--坐标系转换函数 包括饼图.环状条图.玫瑰图.戒指图.坐标翻转. 笛卡尔坐标系(最常见). ArcGIS地理坐标系(地图). Cartesian坐标系. polar极坐标系. ...
- W10: Warning: Changing a readonly file使用vi/vim报错问题解决
使用vi/vim编辑文件的时候出现W10: Warning: Changing a readonly file报错 解决方法: 一.强制保存退出 :wq! 二.ll 查询文件属主,使用属主赋予权限 c ...
- oracle 将电话号码中间4位数以星号*代替
select replace('17665312355',substr('17665312355',4,4),'****') as phone, #类似E ...
- 自动化测试系列(三)|UI测试
UI 测试是一种测试类型,也称为用户界面测试,通过该测试,我们检查应用程序的界面是否工作正常或是否存在任何妨碍用户行为且不符合书面规格的 BUG.了解用户将如何在用户和网站之间进行交互以执行 UI 测 ...
- MPI 学习笔记
目录 MPI学习笔记 MPI准备 概述 前置知识补充 环境部署 1.修改IP及主机名 2.关闭防火墙 3.实现免密码SSH登录 4.配置MPI运行环境 5.测试 程序的执行 编译语句 运行语句 MPI ...
