mel*_*oon 584 javascript object
如果我创建这样的对象:
var obj = {};
obj.prop1 = "Foo";
obj.prop2 = "Bar";
Run Code Online (Sandbox Code Playgroud)
生成的对象总是这样吗?
{ prop1 : "Foo", prop2 : "Bar" }
Run Code Online (Sandbox Code Playgroud)
也就是说,属性是否与我添加它们的顺序相同?
bpi*_*rre 429
不,JavaScript中不保证对象中的属性顺序; 你需要使用一个Map
.
ECMAScript第三版中对象的定义(pdf):
4.3.3对象
对象是Object类型的成员.它是一个无序的属性集合,每个属性都包含一个原始值,对象或函数.存储在对象属性中的函数称为方法.
从ECMAScript 2015开始,使用该Map
对象可能是另一种选择.A Object
与a 共享一些相似之处Map
并保证按键顺序:
Map以插入顺序迭代其元素,而未为Objects指定迭代顺序.
Dav*_*son 180
当前语言规范:从技术上讲,订单未指定.
当前浏览器:订单被保留,除了像"7"这样的键,其解析为整数并由Chrome/V8以不同方式处理.
未来语言规范(> ES2015):一般来说,你可以预期今天订购的东西不会变得无序.新API将保证订单; 现有的API很难改变.有关更多详细信息,请参阅JMM的答案.
下面的最佳链接是Tim Down的评论:
http://code.google.com/p/v8/issues/detail?id=164
该漏洞详细介绍了Chrome实施密钥排序所涉及的设计决策.一个外卖是,对于不解析为整数的字符串键(即"a"或"b",但不是"3"),键在所有主要浏览器上以插入顺序打印,而这种行为不是"标准化",它IS认为浏览器厂商一显著向后兼容性问题.使用风险由您自己承担.
每一个(相当自以为是)的评论:
标准总是遵循实现,这就是XHR的来源,而Google通过实施Gears然后拥抱等效的HTML5功能来做同样的事情.正确的解决方案是让ECMA正式将事实上的标准行为纳入规范的下一版本.
如果您依赖于插入顺序,那么您就不在ECMAScript规范之内,但只要您的密钥不作为整数解析,就在普通浏览器行为的事实标准范围内.
小智 74
普通对象中的属性顺序是Javascript中的复杂主题.
虽然在ES5中明确没有指定任何顺序,但ES2015在某些情况下有订单.给出以下对象:
o = Object.create(null, {
m: {value: function() {}, enumerable: true},
"2": {value: "2", enumerable: true},
"b": {value: "b", enumerable: true},
0: {value: 0, enumerable: true},
[Symbol()]: {value: "sym", enumerable: true},
"1": {value: "1", enumerable: true},
"a": {value: "a", enumerable: true},
});
Run Code Online (Sandbox Code Playgroud)
这导致以下顺序(在某些情况下):
Object {
0: 0,
1: "1",
2: "2",
b: "b",
a: "a",
m: function() {},
Symbol(): "sym"
}
Run Code Online (Sandbox Code Playgroud)
因此,有三个段,可能会改变插入顺序(如示例中所示).类似整数的键根本不会影响插入顺序.
问题是,在ES2015规范中,该订单的保证方法是什么?
以下方法保证显示的顺序:
以下方法/循环保证根本没有订单:
结论:即使在ES2015中,您也不应该依赖Javascript中普通对象的属性顺序.它容易出错.请Map
改用.
Aln*_*tak 66
在撰写本文时,大多数浏览器确实以与插入时相同的顺序返回属性,但显然不能保证行为,因此不应该依赖它们.
在ECMAScript规范常说的:
未指定枚举属性的机制和顺序.
但是在ES2015及更高版本中,将按插入顺序返回非整数键.
JMM*_*JMM 42
整个答案是在规范合规的背景下,而不是任何引擎在特定时刻或历史上所做的事情.
实际问题非常模糊.
属性是否与我添加它们的顺序相同
在什么情况下?
答案是:它取决于许多因素.一般来说,没有.
在这里您可以依赖普通的属性键顺序Objects
:
Object.getOwnPropertyNames()
,Reflect.ownKeys()
,Object.getOwnPropertySymbols(O)
在所有情况下,这些方法都包括非枚举属性键和指定键[[OwnPropertyKeys]]
(如下所示).它们包含的键值(String
和/或Symbol
)的类型不同.在此上下文中String
包括整数值.
Object.getOwnPropertyNames(O)
返回O
自己的String
键属性(属性名称).
Reflect.ownKeys(O)
返回O
自己的String
- 和 - Symbol
键的属性.
Object.getOwnPropertySymbols(O)
返回O
自己的Symbol
键控属性.
[[OwnPropertyKeys]]
顺序基本上是:Strings
按升序排列的整数Strings
,创建顺序中的非整数,创建顺序中的符号.根据哪个函数调用此函数,可能不包括其中一些类型.
特定语言是按以下顺序返回键:
... [正在迭代的对象]的每个自己的属性键
P
,O
它是一个整数索引,按升序数字索引顺序排列......每一个自己的财产关键
P
的O
是一个字符串,但不是整数指数,物业创建顺序......每一个自己的财产关键
P
的O
是一个符号,在属性创建顺序
Map
如果您对有序地图感兴趣,您应该考虑使用Map
ES2015中引入的类型而不是普通的类型Objects
.
Cer*_*nce 18
从 ES2015 开始,某些迭代属性的方法可以保证属性顺序。但不是其他人。不幸的是,不能保证有订单的方法通常是最常用的:
Object.keys
, Object.values
,Object.entries
for..in
循环JSON.stringify
但是,从 ES2020 开始,由于已完成的提案:for-in 机制,规范将保证这些以前不可信方法的属性顺序以与其他方法相同的确定性方式进行迭代。
就像具有保证迭代顺序的方法(如Reflect.ownKeys
和Object.getOwnPropertyNames
)一样,先前未指定的方法也将按以下顺序迭代:
这几乎是每个实现都已经完成的(并且已经完成了很多年),但新提案已使其正式化。
尽管当前的规范保留......迭代顺序“几乎完全未指定,但实际引擎往往更加一致:”
ECMA-262 缺乏特异性并不能反映现实。在过去几年的讨论中,实现者已经观察到 for-in 的行为存在一些限制,任何想要在 Web 上运行代码的人都需要遵循这些限制。
因为每个实现都已经以可预测的方式迭代了属性,所以可以将其放入规范中而不会破坏向后兼容性。
有一些奇怪的情况,目前的实现不同意,在这种情况下,结果的顺序将继续是未指定的。要保证财产秩序:
被迭代的对象及其原型链中的任何东西都不是代理、类型化数组、模块命名空间对象或宿主外来对象。
在迭代过程中,对象及其原型链中的任何东西都没有原型更改。
在迭代过程中,对象及其原型链中的任何内容都没有删除属性。
对象的原型链中没有任何东西在迭代期间添加属性。
在迭代过程中,对象或其原型链中的任何属性都不会改变其可枚举性。
没有不可枚举的属性会影响可枚举的属性。
直到ES2015才保证对象中键的顺序。它是实现定义的。
但是,在ES2015中已指定。像JavaScript中的许多事情一样,这样做是出于兼容性目的,并且通常反映了大多数JS引擎中的现有非官方标准(您知道,谁是例外)。
该顺序在规范中的抽象操作OrdinaryOwnPropertyKeys下定义,该操作支持对对象自己的键进行迭代的所有方法。解释如下,顺序如下:
所有整数索引键(这样的东西"1123"
,"55"
等),在上升的数字顺序。
所有不是整数索引的字符串键,按创建顺序(最早的顺序)。
所有符号键,按创建顺序(最早的顺序)。
说这个顺序不可靠是很愚蠢的-它是可靠的,可能不是您想要的,现代浏览器正确地实现了这个顺序。
某些例外情况包括枚举继承的键的方法,例如for .. in
循环。将for .. in
根据规范循环不保证秩序。
小智 5
正如其他人所说,当您迭代对象的属性时,您无法保证顺序.如果您需要多个字段的有序列表,我建议创建一个对象数组.
var myarr = [{somfield1: 'x', somefield2: 'y'},
{somfield1: 'a', somefield2: 'b'},
{somfield1: 'i', somefield2: 'j'}];
Run Code Online (Sandbox Code Playgroud)
这样,您可以使用常规for循环并具有插入顺序.然后,您可以使用Array排序方法将其排序为新数组(如果需要).
小智 5
刚刚发现这一点很困难。
将 React 与 Redux 结合使用,每次存储更改时,我想要遍历其键以生成子项的状态容器都会刷新(根据 Redux 的不变性概念)。
因此,为了采取Object.keys(valueFromStore)
我使用的Object.keys(valueFromStore).sort()
,这样我至少现在有按键的字母顺序。
小智 5
对象和 MAP 之间的主要区别(举例):
\n它是循环中的迭代顺序,在 Map 中它遵循创建时设置的顺序,而在 OBJECT 中则不然。
\n请参阅:\n对象
\nconst obj = {};\nobj.prop1 = "Foo";\nobj.prop2 = "Bar";\nobj['1'] = "day";\nconsole.log(obj)\n\n**OUTPUT: {1: "day", prop1: "Foo", prop2: "Bar"}**\n
Run Code Online (Sandbox Code Playgroud)\n地图
\n const myMap = new Map()\n // setting the values\n myMap.set("foo", "value associated with 'a string'")\n myMap.set("Bar", 'value associated with keyObj')\n myMap.set("1", 'value associated with keyFunc')\n\nOUTPUT:\n**1. \xe2\x96\xb60: Array[2]\n1. 0: "foo"\n2. 1: "value associated with 'a string'"\n2. \xe2\x96\xb61: Array[2]\n1. 0: "Bar"\n2. 1: "value associated with keyObj"\n3. \xe2\x96\xb62: Array[2]\n1. 0: "1"\n2. 1: "value associated with keyFunc"**\n
Run Code Online (Sandbox Code Playgroud)\n
归档时间: |
|
查看次数: |
198673 次 |
最近记录: |