Reflect.has / Reflect.ownKeys / in / getOwnPropertyDescriptor 等几种获取对象属性的区别

news/2024/7/19 14:53:19 标签: js

可以把获取属性的这些API分成几部分:

  • 均可以获取普通属性,这是必然的…
  • 是否可以获取不可枚举属性
  • 是否可以获取Symbol属性
  • 是否可以获取存在于原型上的属性

而具备访问对象属性的api分为以下部分

  • Reflect 静态方法(has() / ownKeys() 等)
  • Object 静态方法(getOwnPropertyNames 等)
  • in 操作符,包含直接使用或者for in 使用
  • 当然还有.操作符或者[‘key’]这样直接访问

可能ES标准委也觉得这么多访问属性的api多少有些难为开发者。所以api命名的时候,若只能访问自身的属性,而非原型的属性,一般会加上个Own前缀,比如

  • Object.getOwnPropertyDescriptor()
  • Object.getOwnPropertyDescriptors()
  • Object.getOwnPropertyNames()
  • Object.getOwnPropertySymbols()
  • Reflect.getOwnPropertyDescriptor()
  • Reflect.ownKeys()
  • objectInstance.hasOwnProperty()

以上这些api均不能访问对象的原型属性和方法,而且庆幸的是,这些api均可以访问到普通属性,不可枚举属性,以及Symbol私有属性。当然getOwnPropertyNamesgetOwnPropertySymbols 这两个是一对,各自访问各自的那一部分属性,二者加起来恰恰就是所有属性。

以上是第一部分,很好记忆,接着来看看第二部分,即自身属性和原型属性都能访问的api。事实上,没有一个api能够直接获取到包含自身属性和原型属性的集合。

// 不存在能够获取所有属性集合的api.
const allKeys = someObject.getSelfAndPrototypeProperties();

但存在两个api,可以检测所有属性中的任一个属性是否存在于对象中。

  • Reflect.has()
  • in 操作符

静态方法 Reflect.has() 作用与 in 操作符 相同。

以上两个api可以检测到包含自身属性和原型属性,无论普通 / 不可枚举 / 原型。可以把这二者看做是第二部分。

接下来是第三部分,反而是我们经常会用到的:

  • Object.keys()
  • for in 循环

以上两个api均不能访问到不可枚举以及Symbol私有属性。当然for in可以获取到原型属性,而Object.keys不可以。

const foo = {a: 1};
// bar 的原型是foo。bar自身有一个可枚举属性b
const bar = Object.create(foo, {b: {value: 2, enumerable: true}})

console.log(Object.keys(bar)); // b
for (let attr in bar) {console.log(attr)} // b a

最后,使用.操作符和['']的方式访问属性。这是可以访问到普通、不可枚举 、私有以及原型属性。区别于第二部分,由于这两种方式可以赋值,若当前属性是来自于原型,那么赋值之后会怎么样呢?

const foo = {a: 1};
// bar 的原型是foo。bar自身有一个可枚举属性b
const bar = Object.create(foo, {b: {value: 2, enumerable: true}})

bar.a = 3;
console.log(bar.a); // 3
console.log(foo.a); // 1

// 不会多遍历一次a
for (let attr in bar) {console.log(attr)} // b a

如上赋值操作不会修改原型属性。但如果原型属性是只读的呢?

const foo = {a: 1};
Object.freeze(foo);
// bar的原型属性a是只读的。
Object.getOwnPropertyDescriptor(foo, 'a'); // {value: 1, writable: false, enumerable: true, configurable: false}

const bar = Object.create(foo, {b: {value: 2, enumerable: true}})

bar.a = 3;

console.log(bar.a); // 猜猜是多少?

参考:

最后答案参考这里…
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect


http://www.niftyadmin.cn/n/1382555.html

相关文章

swift xcode设置 ,代码折叠,全局折叠 快捷键

在preference text editing 里面打开 function 折叠的项, 折叠方法快捷键: optioncommand left/right 全局折叠快捷键: shiftoptioncommandleft/right 打开左侧面板: command0 /1 常用的快捷键和vs一样类似的功能,喜欢…

scrapy深入学习----(2)

Examples一个小例子学习最好的方法就是有个例子一起学习,Scrapy也不例外。因此,有一个叫做 dirbot的Scrapy 工程作为例子,你可以借助它学习更多Scrapy的知识。它也包含了dmoz spider,在tutorial讲到的那个例子。dirbot 项目可以在…

Amazon全新轻量级服务器端Swift框架:Smoke

Amazon Smoke框架是使用Swift语言编写的全新开源轻量级服务器端框架,用于构建类REST或类RPC的服务。它的架构设计强调易于使用,以及请求处理程序偏向纯函数编程的风格。\\通过Amazon Smoke创建服务需要三个步骤:\\\\t定义处理传入的请求的操作…

Note this is for preview or E2E testing only

当执行npm run serve 的时候,若出现Note this is for preview or E2E testing only,会失去热更新(HMR)的功能。 默认情况下,执行npm run serve会以development的模式启动。但项目中中配置了.env.development&#xff…

Android快速发布项目到jcenter

最近在整理项目的时候,想要上传至Jcenter,可以让大家一句代码就可以引入。就在网上寻找,然而网上有些方法实在是太麻烦,故写此篇文章将心酸历程写下,让各位老司机少走弯路,快速发布。而且最近更坑人的是bin…

CodeForces 593A

题目链接: http://codeforces.com/problemset/problem/593/A 题意: 给你n个字符串,字符串只包含小写字母,从中选取任意个字符串,拼成一封信,这封信中至多有两种字符,输出信的最大长度。 题解&am…

Histats申请Counter网站计数器 - Blog透视镜

为了计算网页被浏览的次数,访客人数等统计数据,作为未来分析之用,可以向Histats申请免费的Counter网站计数器,它的功能相当齐全,同时也会保留一段时间的资料,当作统计比较的资料,更可以进一步付…

windows家庭版使用RDP Wrapper配置远程桌面

前言 windows家庭版是不支持远程桌面的,专业版和企业版是支持的。所以如果电脑的windows是后二者,则可以忽略本文直接配置。 RDP Wrapper github开源软件RDP Wrapper可以帮助家庭版也支持远程桌面的功能。 Github项目地址 从下图所示的Release处下…