在 JavaScript 中,有没有办法用未初始化的实例变量创建对象字面量?
目的是允许使用 for-in 循环遍历成员,以与其他类似对象并行初始化它们,以实现通用代码。目前,我只需要为成员添加临时虚拟值(包括“未定义”),所以我想知道是否有办法绕过必须这样做。
在 JavaScript 中,有没有办法用未初始化的实例变量创建对象字面量?
目的是允许使用 for-in 循环遍历成员,以与其他类似对象并行初始化它们,以实现通用代码。目前,我只需要为成员添加临时虚拟值(包括“未定义”),所以我想知道是否有办法绕过必须这样做。
这很漂亮。它取决于Object.definedProperty
让我们创建一个对象
var obj = Object.create({});
定义一些enumerable
属性。这些将在我们迭代对象时出现
Object.defineProperty(obj, 'hardwork', {
configurable: true,
enumerable: true,
get: function() {
// caution: hard work below!
console.log("hard work began");
return Math.random();
}
});
Object.defineProperty(obj, 'reallyhardwork', {
configurable: true,
enumerable: true,
get: function() {
// caution: really hard work below!
console.log("really hard work began");
return [Math.random(), Math.random(), Math.random()];
}
});
这是一个不可枚举的属性;它不会包含在 for..in 循环中
Object.defineProperty(obj, 'hidden', {
configurable: true,
enumerable: false,
get: function() {
console.log("hidden work happening now!");
return "you should not see this";
}
});
最后,让我们实际做一些工作
console.log("begin working");
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
console.log(obj[prop]);
}
}
console.log("work ended");
输出
"begin working"
"hard work began"
0.038129367399960756
"really hard work began"
[ 0.9397948638070375, 0.6731829405762255, 0.2854277777951211 ]
"work ended"
注意:隐藏属性未显示在输出中,但如果您需要它仍然可用。
obj.hidden
// => hidden work happening now!
// => you should not see this
将此与以下内容进行比较
var obj = {
hardwork: Math.random(),
reallyhardwork: [Math.random(), Math.random(), Math.random()],
hidden: "you should not see this"
};
这些Math.random()
调用是在定义对象时运行的,这意味着所有艰苦的工作都是预先完成的;不像上面的例子那样在迭代期间延迟加载。另请注意,如果您希望任何属性不包含在循环中,这种方式将行不通。您将在下面看到隐藏的属性已显示。
// no work is done except for iterating through values that have already been defined
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
console.log(obj[prop]);
}
}
输出
0.7174121951684356
[ 0.7939756268169731, 0.4218691026326269, 0.8476794681046158 ]
"you should not see this"
这真的很简单,只需将其设置为undefined,例如使用function。
function createProperties(o, k) {
var i;
for (i = 0; i < k.length; ++i)
o[k[i]] = undefined; // or `void 0`
}
然后
var myObj = {}, key;
createProperties(myObj, ['foo', 'bar']);
for (key in myObj) console.log(key, myObj[key]);
// foo undefined
// bar undefined
这样做比使用null
或可能更有用的东西没有真正的好处。
为什么我建议undefined?考虑以下。
(function () {
"use strict";
var foo;
console.log(foo, foo === undefined); // logs undefined true
bar; // ReferenceError: bar is not defined
}());
所以var x;
与 有相同的结果var x = undefined;
。接下来,考虑
var arr1 = new Array(1),
arr2 = [undefined];
arr1[0]; // undefined
arr2[0]; // undefined
arr1[0] === arr2[0]; // true
// look pretty similar, HOWEVER
arr1.hasOwnProperty(0); // false
arr2.hasOwnProperty(0); // true
因此,尽管您可能会在某些地方出现未定义,但它不会告诉您该属性是否已初始化
您唯一的办法是在实例上实际定义这些键,否则您无法枚举此属性,但为避免出现伪数据,您只需将值设置为undefined
.
var foo = function() {
this.someInstanceMember = undefined;
};
var bar = new foo();
像这样的东西Object.keys(bar)
将显示someInstanceMemeber
已定义,for in 循环将获取它并且"someInstanceMember" in bar
is true
。