我正在尝试编写一个需要知道传入的对象的属性名称的函数,如下所示:
var data = { "key1":"value1", "key2":"value2", etc}
^ i want the string value "key1"
Run Code Online (Sandbox Code Playgroud)
如何从中检索字符串"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
}
Run Code Online (Sandbox Code Playgroud)
T.J*_*der 21
在我们查看选项之前,请快速了解JavaScript中有关属性的四个关键事项:
Symbols.a = ['x', 'y', 'z']定义了三个属性,其名称是一个数组"0","1"和"2".当我们a[0]访问第一个时,数字0将转换为字符串.(理论上;再次允许JavaScript实现进行优化.)所有这些属性都可以被发现和枚举(甚至是不可枚举的属性).您有以下几种选择:
for-in环(规格 | MDN),使用或不使用hasOwnProperty内循环后卫"拥有"和继承的属性区分.(不包括用Symbols 命名的属性.)循环遍历属性的名称.Object.keys(spec | MDN)(ES5 +),返回对象自己的可枚举属性的名称数组.(不包括用Symbols 命名的属性.)Object.getOwnPropertyNames(spec | MDN)(ES5 +),返回对象自身属性名称的数组,无论它们是否可枚举.(不包括用Symbols 命名的属性.)Reflect.enumerate(spec | MDN)(ES2015 +),它返回一个对象的可枚举属性名称的迭代器,包括它继承的属性.(不包括以Symbols 命名的属性.)Object.getOwnPropertySymbols(spec | MDN)(ES2015 +),它返回一个以Symbols 命名的对象自己的属性名称数组,而不管它们是否可枚举.(留下用字符串命名的.)Reflect.ownKeys(spec | MDN)(ES2015 +),返回对象自身属性名称的数组,无论它们如何命名(Symbol或字符串),以及它们是否可枚举.正如你所看到的,大部分的操作只包括其名称是字符串的属性,只有Object.getOwnPropertySymbols和Reflect.ownKeys给我们命名的那些Symbol秒.
对于for-in或,未定义键的顺序(甚至在ES2015中也没有)Object.keys.在ES2015和上面,它被用于其他四个定义,由[[OwnPropertyKeys]]和(在适用情况下)[[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
});
Run Code Online (Sandbox Code Playgroud)
(Object.create was added in ES5, but the version of it taking just one argument [as above] can easily be shimmed/polyfilled for obsolete JavaScript engines, like the one in IE8. Object.defineProperty was also added in ES5, and cannot be correctly shimmed/polyfilled.)
Since most of the operations only involve properties named by strings, we're ignoring Symbols for now.
Once the code above runs, we have this in memory (the * next to a name indicates it's a non-enumerable property):
+?????????????????+
Object.prototype????????????????????????????????+??>| toString* |??>(...a function...)
| | valueOf* |??>(...a function...)
| | hasOwnProperty* |??>(...a function...)
| | ... |
| +?????????????????+
|
+???????????????+ |
proto????????????????????+??>| [[Prototype]] |??+
| | one: 1 |
| +???????????????+
|
+???????????????+ |
obj??>| [[Prototype]] |??+
| two: 2 |
| three: 3 |
| four*: 4 |
+???????????????+
With that setup, let's look at our options:
for-infor-in loops through the names of all of an object's properties (including ones it inherits from its prototype) whose names are strings (leaving out any whose names are Symbols).
for (var name in obj) {
// name is the name of each property, so:
console.log(name + " = " + obj[name]);
}
Run Code Online (Sandbox Code Playgroud)
// 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]);
}Run Code Online (Sandbox Code Playgroud)
With that, we see
two = 2 three = 3 one = 1
......或类似的.您在属性中看到的顺序未定义,即使在ES2015中也未定义.
for-in带着hasOwnProperty警卫如果我们想要循环,但忽略继承的属性,我们可以添加一个hasOwnProperty检查:
for (var name in obj) {
if (obj.hasOwnProperty(name)) {
console.log(name + " = " + obj[name]);
}
}
Run Code Online (Sandbox Code Playgroud)
// 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]);
}
}Run Code Online (Sandbox Code Playgroud)
有了这个,我们看到了
two = 2 three = 3
我们没有看到,one因为它是继承的.
既然hasOwnProperty是对象的一个方法,理论上它可以用一个没有返回我们期望的版本来覆盖:
obj.hasOwnProperty = function() {
return true;
};
Run Code Online (Sandbox Code Playgroud)
......这会欺骗我们的循环.这通常不是问题,但如果你想要防范它,请Object.prototype改用:
var hasOwn = Object.prototype.hasOwnProperty;
for (var name in obj) {
if (hasOwn.call(obj, name)) {
console.log(name + " = " + obj[name]);
}
}
Run Code Online (Sandbox Code Playgroud)
当然,有人也可以分配给该Object.prototype.hasOwnProperty物业,但如果他们这样做,相当多的事情可能会破裂.
Object.keys (ES5 +,易于整理/聚合填充)Object.keys gives us an array of the names of the object's own, enumerable properties named with strings. So it doesn't include inherited properties, properties marked non-enumerable, or properties named with Symbols.
var propNames = Object.keys(obj);
Run Code Online (Sandbox Code Playgroud)
We can then loop over the entries in that array in any of several ways, such as forEach:
propNames.forEach(function(name) {
console.log(name + " = " + obj[name]);
});
Run Code Online (Sandbox Code Playgroud)
// 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]);
});Run Code Online (Sandbox Code Playgroud)
With our sample setup, that gives us:
two = 2 three = 3
The order of the names in the array is not defined by the specification, not even in ES2015.
Object.getOwnPropertyNames (ES5+)Object.getOwnPropertyNames returns an array of the names of the object's own properties named with strings, whether enumerable or not. It leaves out properties named with Symbols.
var propNames = Object.getOwnPropertyNames(obj);
propNames.forEach(function(name) {
console.log(name + " = " + obj[name]);
});
Run Code Online (Sandbox Code Playgroud)
// 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]);
});Run Code Online (Sandbox Code Playgroud)
With our sample setup, that gives us:
two = 2 three = 3 four = 4
The order of the names in the array is defined by the [[OwnPropertyKeys]] operation in the specification, which says the order is:
So we get two, three, four because none of those fits the spec's definition of an integer index, and that's the order in which we added the properties. If we added them in a different order, or included ones that qualified as indexes, we'd get different results:
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]);
});
Run Code Online (Sandbox Code Playgroud)
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]);
});Run Code Online (Sandbox Code Playgroud)
Gives us:
0 = zero four = 4 two = 2 three = 3
0 was first because although it's a string, it fits the criteria for an integer index. Then we get four because it was created first, then two, then three.
Reflect.enumerate (ES2015)Reflect.enumerate was removed in 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).
We can use the new for-of loop to loop over them:
for (let name of Reflect.enumerate(obj)) {
console.log(name + " = " + obj[name]);
}
Run Code Online (Sandbox Code Playgroud)
With our setup, that gives us:
two = 2 three = 3 one = 1
one is at the end because it's inherited, and "own" properties come first.
Note: Again, since ES2015 is relatively new as of this writing, some JavaScript engines may not implement the Reflect object yet.
Object.getOwnPropertySymbols (ES2015+)Object.getOwnPropertySymbols returns an array of an object's own properties named with Symbols, regardless of whether they're enumerable. (Leaves out ones named with strings.) We'll need a different setup to try this, since we didn't include Symbol-named properties in our main setup. Since inherited properties are ignored, we'll keep it simple:
var obj3 = {};
obj3[Symbol("x")] = "ecks";
obj3[1] = "one";
obj3[Symbol("y")] = "why";
obj3.z = "zee";
Object.getOwnPropertySymbols(obj3).forEach(function(symbol) {
console.log(symbol.toString() + " = " + obj3[symbol]);
});
Run Code Online (Sandbox Code Playgroud)
var obj3 = {};
obj3[Symbol("x")] = "ecks";
obj3[1] = "one";
obj3[Symbol("y")] = "why";
obj3.z = "zee";
Object.getOwnPropertySymbols(obj3).forEach(function(symbol) {
console.log(symbol.toString() + " = " + obj3[symbol]);
});Run Code Online (Sandbox Code Playgroud)
Output:
Symbol(x) = ecks Symbol(y) = why
z wasn't listed because it has a string name, not a Symbol name. Symbol(x) was first because it was created first.
There's a lot more to Symbols than shown here, but as you can see, if we give a symbol a name, we can use toString to get back Symbol(the name here) as a string. Interesting, we have to call toString explicitly (thesymbol.toString()) or use String(theSymbol); the + operator will not do it for us when appending a symbol to a string.
Reflect.ownKeys (ES2015+)Reflect.ownKeys returns an array of an object's own properties no matter how they're named (Symbol or string), and whether they're enumerable or not. It ignores inherited properties:
var obj3 = {};
obj3[Symbol("x")] = "ecks";
obj3[1] = "one"
obj3[Symbol("y")] = "why";
obj3.z = "zee";
Reflect.ownKeys(obj3).forEach(function(key) {
console.log(key.toString() + " = " + obj3[key]);
});
Run Code Online (Sandbox Code Playgroud)
var obj3 = {};
obj3[Symbol("x")] = "ecks";
obj3[1] = "one"
obj3[Symbol("y")] = "why";
obj3.z = "zee";
Reflect.ownKeys(obj3).forEach(function(key) {
console.log(key.toString() + " = " + obj3[key]);
});Run Code Online (Sandbox Code Playgroud)
Output:
1 = one z = zee Symbol(x) = ecks Symbol(y) = why
Note the order, which is defined by [[OwnPropertyKeys]]: 1 was first because it's a string that qualifies as an integer index. z was next because it's a string-named property. Then we have the Symbol-named properties, in the order in which they were created.
var data = { "key1":"value1", "key2":"value2"}; //etc
for (var prop in data) {
var propName = prop;
var propVal = data[prop];
// do something with your new variables
}
Run Code Online (Sandbox Code Playgroud)
是的,就这么简单.
| 归档时间: |
|
| 查看次数: |
15510 次 |
| 最近记录: |