Javascript:检索对象属性名称

2024-03-14

我正在尝试编写一个需要知道传入对象的属性名称的函数,如下所示:

var data = { "key1":"value1", "key2":"value2", etc}
               ^ i want the string value "key1"

如何从中检索字符串“key1”data?我知道我可以像这样动态设置属性data[prop]=value但我想知道什么prop来自传入的对象。

如果这没有意义,我想我可以尝试解释更多。谢谢!

我最终想做类似的事情:

for (var i = 0; i<data.length; i++)
{
    var name = data[i].getPropertyName() <--- not a real function
    // do stuff
}

在我们查看选项之前,先快速了解一下有关 JavaScript 属性的四个关键事项:

  1. 对象可以拥有自己的属性,以及从原型对象继承的属性。
  2. 属性可以是可枚举的 or 不可枚举.
  3. 属性的名称可以是strings,或(从 ES2015/ES6 开始)名称Symbols.
  4. 属性不能有数字名称,比如 1。有时我们的行为就像它们一样,就像我们处理数组时一样,但它们却不然。标准阵列根本不是真正的数组 http://blog.niftysnippets.org/2011/01/myth-of-arrays.html(根据规范;JavaScript 实现可以在可能的情况下进行优化),数组中的条目是名称为字符串的对象属性。所以a = ['x', 'y', 'z']定义一个具有三个属性的数组,其名称为"0", "1", and "2"。当我们这样做时a[0]访问第一个,数字0被转换为字符串。 (理论上;同样,JavaScript 实现是允许优化的。)

所有这些属性都可以被发现和枚举(甚至是不可枚举的属性)。 您有多种选择:

  • A for-in loop (spec http://www.ecma-international.org/ecma-262/6.0/index.html#sec-for-in-and-for-of-statements | MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in),有或没有hasOwnProperty http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.prototype.hasownproperty在循环内部进行保护以区分“自己的”属性和继承的属性。 (不包括以Symbols.) 循环names的属性。
  • Object.keys (spec http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.keys | MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) (ES5+),它返回对象自身的可枚举属性的名称数组。 (不包括以Symbols.)
  • Object.getOwnPropertyNames (spec http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.getownpropertynames | MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames) (ES5+),它返回对象自身属性名称的数组,无论它们是否可枚举。 (不包括以Symbols.)
  • Reflect.enumerate (spec http://www.ecma-international.org/ecma-262/6.0/index.html#sec-reflect.enumerate | MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/enumerate) (ES2015+), which returns an iterator for the names of the enumerable properties of an object, including ones it inherits. (Does not include properties named with Symbols.) It was removed in ES2016.
  • Object.getOwnPropertySymbols (spec http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.getownpropertysymbols | MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertySymbols) (ES2015+),它返回一个对象自身属性的名称数组Symbols,无论它们是否可枚举。 (省略那些用字符串命名的。)
  • Reflect.ownKeys (spec http://www.ecma-international.org/ecma-262/6.0/index.html#sec-reflect.ownkeys | MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/ownKeys) (ES2015+),它返回对象自身属性名称的数组,无论它们如何命名 (Symbol或字符串),以及它们是否可枚举。

正如你所看到的,大多数操作只包含名称为字符串的属性,只有Object.getOwnPropertySymbols and Reflect.ownKeys给我们命名为Symbols.

键的顺序未定义(甚至在 ES2015 中也未定义):for-in or Object.keys。在 ES2015 及以上版本中,is为其他四个定义,由[[OwnPropertyKeys]] http://www.ecma-international.org/ecma-262/6.0/index.html#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys和(如适用)[[Enumerate]] http://www.ecma-international.org/ecma-262/6.0/index.html#sec-ordinary-object-internal-methods-and-internal-slots-enumerate运营。 (由于 ES2015 [截至撰写本文时] 仍相对为人所知,因此可能并非所有 JavaScript 引擎都正确实现了该顺序。)

让我们看一下例子。首先,一些设置:

// Create an object with one "own" property (plus the ones it
// inherits from Object.prototype):
var proto = {
    one: 1
}

// Create an object that uses the above as its prototype
var obj = Object.create(proto);

// Add a couple of enumerable properties
obj.two = 2;
obj.three = 3;

// Add a non-enumerable property (by default, properties created
// with Object.defineProperty are non-enumerable)
Object.defineProperty(obj, "four", {
   value: 4,
   configurable: true,
   writable: true
});

(Object.createES5 中添加了这一功能,但仅采用一个参数的版本 [如上所述] 可以轻松地为过时的 JavaScript 引擎(例如 IE8 中的引擎)进行填充/填充。Object.definePropertyES5 中也添加了该内容,并且无法正确填充/填充。)

由于大多数操作仅涉及由字符串命名的属性,因此我们忽略Symbol现在是这样。

一旦上面的代码运行,我们就会在内存中保存它(*名称旁边的 表示它是不可枚举的属性):



                                                    +−−−−−−−−−−−−−−−−−+
Object.prototype−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−−>| toString*       |−−>(...a function...)
                                                |   | valueOf*        |−−>(...a function...)
                                                |   | hasOwnProperty* |−−>(...a function...)
                                                |   | ...             |
                                                |   +−−−−−−−−−−−−−−−−−+
                                                |
                             +−−−−−−−−−−−−−−−+  |
proto−−−−−−−−−−−−−−−−−−−−+−−>| [[Prototype]] |−−+
                         |   | one: 1        |
                         |   +−−−−−−−−−−−−−−−+
                         |
      +−−−−−−−−−−−−−−−+  |
obj−−>| [[Prototype]] |−−+
      | two: 2        |
      | three: 3      |
      | four*: 4      |
      +−−−−−−−−−−−−−−−+
  

有了这个设置,让我们看看我们的选项:

for-in

for-in循环遍历名称为字符串的对象的所有属性(包括从其原型继承的属性)的名称(忽略名称为字符串的所有属性)Symbols).

for (var name in obj) {
    // name is the name of each property, so:
    console.log(name + " = " + obj[name]);
}
// Create an object with one "own" property (plus the ones it
// inherits from Object.prototype):
var proto = {
    one: 1
}

// Create an object that uses the above as its prototype
var obj = Object.create(proto);

// Add a couple of enumerable properties
obj.two = 2;
obj.three = 3;

// Add a non-enumerable property (by default, properties created
// with Object.defineProperty are non-enumerable)
Object.defineProperty(obj, "four", {
   value: 4,
   configurable: true,
   writable: true
});

for (var name in obj) {
    // name is the name of each property, so:
    console.log(name + " = " + obj[name]);
}

至此,我们看到



two = 2
three = 3
one = 1
  

...或类似的。即使在 ES2015 中,您看到的属性的顺序也没有定义。

for-in with a hasOwnProperty guard

如果我们想要循环,但忽略继承的属性,我们可以添加一个hasOwnProperty check:

for (var name in obj) {
    if (obj.hasOwnProperty(name)) {
        console.log(name + " = " + obj[name]);
    }
}
// Create an object with one "own" property (plus the ones it
// inherits from Object.prototype):
var proto = {
    one: 1
}

// Create an object that uses the above as its prototype
var obj = Object.create(proto);

// Add a couple of enumerable properties
obj.two = 2;
obj.three = 3;

// Add a non-enumerable property (by default, properties created
// with Object.defineProperty are non-enumerable)
Object.defineProperty(obj, "four", {
   value: 4,
   configurable: true,
   writable: true
});

for (var name in obj) {
    if (obj.hasOwnProperty(name)) {
        console.log(name + " = " + obj[name]);
    }
}

至此,我们看到



two = 2
three = 3
  

我们没有看到one因为它是遗传的。

Since hasOwnProperty是对象上的一个方法,理论上它可以被一个没有返回我们期望的版本覆盖:

obj.hasOwnProperty = function() {
    return true;
};

...这会欺骗我们上面的循环。这通常不是问题,但如果您想防范它,请使用Object.prototype反而:

var hasOwn = Object.prototype.hasOwnProperty;
for (var name in obj) {
    if (hasOwn.call(obj, name)) {
        console.log(name + " = " + obj[name]);
    }
}

当然,有人可以分配给Object.prototype.hasOwnProperty财产也是如此,但如果这样做,相当多的东西可能会损坏。

Object.keys(ES5+,易于填充/填充)

Object.keys给我们一个对象名称的数组自己的,可枚举的用字符串命名的属性。因此它不包括继承的属性、标记为不可枚举的属性或以Symbols.

var propNames = Object.keys(obj);

然后,我们可以通过多种方式循环遍历该数组中的条目,例如forEach:

propNames.forEach(function(name) {
    console.log(name + " = " + obj[name]);
});
// Create an object with one "own" property (plus the ones it
// inherits from Object.prototype):
var proto = {
    one: 1
}

// Create an object that uses the above as its prototype
var obj = Object.create(proto);

// Add a couple of enumerable properties
obj.two = 2;
obj.three = 3;

// Add a non-enumerable property (by default, properties created
// with Object.defineProperty are non-enumerable)
Object.defineProperty(obj, "four", {
   value: 4,
   configurable: true,
   writable: true
});

var propNames = Object.keys(obj);
propNames.forEach(function(name) {
    console.log(name + " = " + obj[name]);
});

通过我们的示例设置,我们可以得到:



two = 2
three = 3
  

规范中没有定义数组中名称的顺序,即使在 ES2015 中也没有定义。

Object.getOwnPropertyNames (ES5+)

Object.getOwnPropertyNames返回以字符串命名的对象自身属性名称的数组,无论是否可枚举。它省略了命名为的属性Symbols.

var propNames = Object.getOwnPropertyNames(obj);
propNames.forEach(function(name) {
    console.log(name + " = " + obj[name]);
});
// Create an object with one "own" property (plus the ones it
// inherits from Object.prototype):
var proto = {
    one: 1
}

// Create an object that uses the above as its prototype
var obj = Object.create(proto);

// Add a couple of enumerable properties
obj.two = 2;
obj.three = 3;

// Add a non-enumerable property (by default, properties created
// with Object.defineProperty are non-enumerable)
Object.defineProperty(obj, "four", {
   value: 4,
   configurable: true,
   writable: true
});

var propNames = Object.getOwnPropertyNames(obj);
propNames.forEach(function(name) {
    console.log(name + " = " + obj[name]);
});

通过我们的示例设置,我们可以得到:



two = 2
three = 3
four = 4
  

数组中名称的顺序由[[OwnPropertyKeys]] http://www.ecma-international.org/ecma-262/6.0/index.html#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys规范中的操作,其顺序为:

  • 符合条件的属性名称整数索引 http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object-type,按数字顺序。
  • 其他属性的名称,按照属性的创建顺序排列。

所以我们得到two, three, four因为这些都不符合规范对整数索引的定义,而这就是我们添加属性的顺序。如果我们以不同的顺序添加它们,或者包含符合索引的顺序,我们会得到不同的结果:

var obj2 = {};
obj2.four = 4;
obj2[0] = "zero";
obj2.two = 2;
obj2.three = 3;
Object.getOwnPropertyNames(obj2).forEach(function(name) {
    console.log(name + " = " + obj2[name]);
});
var obj2 = {};
obj2.four = 4;
obj2[0] = "zero";
obj2.two = 2;
obj2.three = 3;
Object.getOwnPropertyNames(obj2).forEach(function(name) {
    console.log(name + " = " + obj2[name]);
});

给我们:



0 = zero
four = 4
two = 2
three = 3
  

0首先是因为虽然它是一个字符串,但它符合整数索引的标准。然后我们得到four因为它是先创建的,然后two, then three.

Reflect.enumerate (ES2015) Removed in ES2016

Reflect.enumerate在 ES2016 中被删除。

Reflect.enumerate uses the new iterator feature of ES2015. It returns an iterator that will iterate over the names of the string-named enumerable properties of the object, including inherited ones, skipping ones named with Symbol or that aren't enumerable. First it visits the "own" properties (in the order defined by [[OwnPropertyKeys]], and then inherited properties (unless they've been hidden by "own" properties).

我们可以使用新的for-of循环遍历它们:

for (let name of Reflect.enumerate(obj)) {
    console.log(name + " = " + obj[name]);
}

通过我们的设置,我们可以得到:



two = 2
three = 3
one = 1
  

one位于最后,因为它是继承的,并且“自己的”属性排在第一位。

注意:同样,由于 ES2015 在撰写本文时相对较新,因此某些 JavaScript 引擎可能无法实现Reflect还没有对象。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Javascript:检索对象属性名称 的相关文章

  • 我是否需要关心异步 Javascript 的竞争条件?

    假设我加载了一些我知道在将来某个时候会调用的 Flash 影片window flashReady并将设置window flashReadyTriggered true 现在我有一个代码块 我想在闪存准备好时执行它 我希望它立即执行 如果wi
  • 访问 .js 文件中的 Nuxt 插件

    假设我有一个脚本文件 foo js function doStuff how to access store and other plugins here export default doStuff 如果不将调用组件作为参数传递 我如何访
  • 如何抑制 IE9 window.close() 确认消息

    应用 window close 函数后 IE9 会引发 您正在查看的网页正在尝试关闭 消息 有没有办法在不更改应用程序代码的情况下 而是通过更改一些特定于 IE 的注册表项来抑制此消息 如果窗口不是由脚本打开的 IE 不允许在没有确认的情况
  • 每次用户在地址栏中按 Enter 时,Firefox 插件都会执行某些操作

    我正在尝试编写一个扩展程序 用于监视每次有人在使用地址栏时按下回车键时的情况 步骤将类似于 用户在地址栏中输入一堆文本并按 Enter 键 我的插件启动并接收用户输入的内容 然后我的插件决定如何处理用户输入的字符串 我通过使用在步骤 2 中
  • 如果文本过滤器在 ng-repeat 中没有返回结果,则显示消息

    假设我们有一个带有文本过滤器的 ng repeat
  • 检测 SVGAnimatedString 的类名

    我在构建 SVG 地图时遇到问题 触发的功能 g 上的 onmouseover 不起作用 我当时用的 window onmouseover function e console log e target className 查看类名是否有问
  • 正则表达式没有按预期工作?

    我有这个正则表达式 new RegExp a z 0 9 ig 我正在测试一个不应该工作的字符串 vc 但它确实通过了测试 而且它不应该 new RegExp a z 0 9 ig test vc true 但如果我删除其中一个 or or
  • webpack 加载器并包含

    我是 webpack 的新手 我正在尝试了解加载器及其属性 例如测试 加载器 包含等 这是我在 google 中找到的 webpack config js 的示例片段 module loaders test js loader babel
  • 如何处理 React JSX 中的长类名?

    假设我在 React JSX 中渲染这个组件 render return h1 Some text h1 这些类触发我的 JS linter 的行太长 而且很难阅读 怎样才能分开长className将 React 组件中的属性分成多行而不破
  • 为什么发送 fetch() 时我的响应数据未定义?

    我正在尝试在客户端使用 fetch 将数据发布到我的 NodeJS 服务器或从我的 NodeJS 服务器发布数据 服务器很好地收到了 post 请求 我能够记录 req 变量 但是当我 res send any data 时 客户端无法检测
  • jquery 中 DOM 元素的手动垃圾回收是否可以提高浏览器性能?

    在性能范围内 删除不再需要的元素是否有意义 或者浏览器是否对代码中未进一步引用的 dom 元素执行自动垃圾收集 some element fadeOut 1000 function el el remove lt does this mak
  • ES6 模板文字可以在运行时替换(或重用)吗?

    tl dr 是否可以制作可重用的模板文字 我一直在尝试使用模板文字 但我想我就是不明白 现在我感到沮丧 我的意思是 我想我明白了 但 它 不应该是它的运作方式 或者它应该如何实现 它应该变得不同 我看到的所有示例 甚至标记模板 都要求 替换
  • 原型链、构造函数、继承

    我正在玩 javascript 原型 我是新手 所以我有一个小问题 我正在用这个article http mckoss com jscript object htm作为指导 我已经定义了产品和书籍 目的是什么Book prototype c
  • 允许在 Safari 上聊天应用程序使用 audio.play()

    由于苹果禁用了自动播放音频的功能HTMLMedia Element play https developer mozilla org en US docs Web API HTMLMediaElement play在没有用户交互的 java
  • NodeJS 错误堆栈未定义 [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我正在使用节点检查器 我注意到new Error 有未定义的堆栈 如果我将此值分配给一个变量 该变量将显示堆栈未定义 有趣的是 跑步new
  • 用空字符串替换状态:Javascript

    我有这个网址 website com con blog true 我在 javascript 中所做的是 if getURLparams blog RandomFunction change the url window history r
  • 图像未显示在从 HTML 创建的 PDF 上

    我想动态创建 PDF 这意味着我将从 Google Drive 获取文件 然后将它们放入 HTML 代码中 并尝试从中创建 PDF 一切工作正常 除了图像没有显示 我现在正在做的是 从 HTML 字符串创建 HtmlOutput 获取该 H
  • 如何使用 Typescript 设置 Material-UI for React?

    我在将 Material UI 添加到我的 React 项目中时遇到了一些问题 该项目是用 Typescript 编程的 根据教程 我首先添加react tab event plugin import injectTapEventPlugi
  • Nodejs 解码 base64 并使用流将它们保存到文件中

    在我的node js应用程序中 我使用以下代码行解码base64编码的图像 const fileDataDecoded Buffer from base64EncodedfileData base64 到目前为止 我可以使用以下代码编写一个
  • 将数组数组的字符串转换为 Javascript 数组数组的优雅方法?

    我有一个 ajax 请求 它返回一个值列表 如下所示 5 5 5 6 15 15 7 13 12 我需要它是一个带有数字的 javascript 数组 5 5 5 6 15 15 7 13 12 我尝试将 和 替换为 然后用 分割和 for

随机推荐

  • 如何自动删除项目的所有system.out.println语句,包括所有多行Sop语句[重复]

    这个问题在这里已经有答案了 实际上我想自动化删除所有的过程System out println 在将项目交付给客户之前 对整个项目进行陈述 怎么做 按 ctrl H 转到文件搜索 将包含文本填充为System out println 文件名
  • 将 std::bind 与成员函数一起使用,该参数是否使用对象指针?

    使用时std bind要绑定成员函数 第一个参数是对象this指针 然而 它可以将对象作为指针传递 也可以不传递 例如 请参见以下程序 include
  • 使用转换后的边界进行布局

    我已经缩放了窗格中的一个节点 但窗格的布局考虑了边界 没有任何转换 我希望它考虑到转换后的边界 例如 和代码 import javafx application Application import javafx geometry Pos
  • 如何在 Postgres.app 中降级/使用以前版本的 Postgres DB

    我已经从这里安装了 Postgres app http postgresapp com http postgresapp com 几天以前 它附带 Postgres 9 4 4 今天我发现我使用的软件官方只支持Postgres 9 3 9
  • Javascript导入包无法解析模块说明符

    我正在尝试导入使用 npm 下载的模块 我的 json 文件是 name nodejs web app1 version 0 0 0 description NodejsWebApp1 main server js author name
  • 致命异常:iOS 上的 NSInternalInconsistencyException 崩溃

    几天来我一直在尝试重新创建和研究这个问题 但我不会去任何地方 这是堆栈跟踪 任何人都可以阐明正在发生的事情吗 我认为这与远程通知有关 不久前 当我安装 firebase sdk 时 问题就开始了 当时事故发生的次数并不多 但现在 事故发生的
  • 带有 pandas 数据框的子图

    我想使用 pandas 数据框 称为 df 在图上创建多个子图 我原来的情节在这里 df plot x month y number title open by month color blue 我在本网站的 使用图形和子图 部分尝试了多次
  • 我如何定义“其余宽度”?

    这是我的代码 function tags input on focusout function var txt this value replace a z0 9 ig allowed characters if txt span span
  • 如何运行 Spark Java 程序

    我为 Spark 编写了一个 Java 程序 但是如何从 Unix 命令行运行和编译它 编译运行时是否必须包含任何 jar 结合官方步骤快速入门指南 https spark apache org docs latest quick star
  • D 中的枚举与不可变

    有什么区别 enum i 2 enum s Hello and immutable i 2 immutable s Hello 在 D 2 0 中 An enum是用户定义的类型 而不是变量 enum e 2 是一个 像这样的东西的简写en
  • 查找但不深入到包含搜索文件的目录

    我有几个由 pom xml 或类似配置的项目 我想使用 linux file 命令来定位这些项目 例如经过find name pom xml 然而 由于路径很深 这需要一些时间 我想用find prune当我已经找到文件时停止在子目录中搜索
  • 在哪里使用 Redux 处理计算属性?

    使用 Redux 时 存储应该是唯一的事实来源 并且没有冗余 假设商店的一部分代表有名字和年龄的人 传统面向对象编程中的 person 类可能如下所示 class Person constructor first last birthday
  • 抽象控件中的 VisualState

    我有一个抽象的 BaseControl 其中包含依赖项属性以及默认样式和 VisualState 我想在继承的控件中使用这些 VisualState 据我所知 设置继承控件的模板不会使 VisualState 访问它需要更新的 UIElem
  • 在 .net 5 控制台应用程序中利用用户机密

    我正在构建一个简单的控制台应用程序来处理大型 CSV 文件 SDK版本5 0 202我使用的是 Manjaro Linux CODE using System using System Text using TinyCsvParser us
  • Android 资源限定符 -sw#dp 与 -w#dp

    假设我正在为屏幕尺寸等于或大于 600dp 的设备开发不同的布局 我想使用 android 3 2 后的资源限定符 我创建了一个名为layout sw600dp并将我的布局放在那里 但同时我可以创建一个名为的文件夹layout w600dp
  • 查明文件是否已更改

    我想查明自上次启动 shell 脚本以来文件是否已被修改 也许可以通过创建布尔值或其他东西 也许可以将上次运行脚本的时间保存在一个文本文件中 下次启动脚本时它应该读取该文件 然后它应该找出哪些文件已更改 以便我可以检查是否有文件已使用以下内
  • Laravel 5.8 中 Pusher 连接失败

    我在 laravel 5 4 中使用 Pusher 没有任何问题 但现在我尝试使用 laravel 5 8 但出现以下错误 我已经尝试了我能想到的一切 甚至改变了encrypted to false万一 我三次检查了我的推送者凭据 Lara
  • uifont“Impact”不适用于 iOS

    我正在尝试使用 Impact ttf 它是 OSX 内置的 但在 xcode 上看不到自定义字体 所以我将它包含在我的项目中 如屏幕所示并使用 UIFont font1 UIFont fontWithName Impact ttf size
  • 在 iOS SDK 4.2 上构建越狱设备

    我有一个通过 Cydia 分发的应用程序 它没什么黑科技 只是一个连接到 Web API 的 GUI 我上次提交更新是在 SDK 4 0 之前 我使用了可用的说明here http thebigboss org hosting reposi
  • Javascript:检索对象属性名称

    我正在尝试编写一个需要知道传入对象的属性名称的函数 如下所示 var data key1 value1 key2 value2 etc i want the string value key1 如何从中检索字符串 key1 data 我知道