使用未初始化的成员创建JS对象文字

时间:2013-07-17 22:41:10

标签: javascript

在JavaScript中,有没有办法用未初始化的实例变量创建对象文字?

目的是允许使用for-in循环遍历成员,以便为了通用代码而与其他类似对象并行地初始化它们。目前,我只需要为成员添加临时虚拟值(包括“未定义”),所以我想知道是否有办法绕过必须这样做。

3 个答案:

答案 0 :(得分:2)

这很漂亮。这取决于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"

答案 1 :(得分:0)

这很简单,只需将其设置为 undefined ,例如使用功能

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 ,但它并没有告诉您该属性是否已初始化

答案 2 :(得分:0)

您唯一的选择是在实例上实际定义这些键,否则您无法枚举此属性,但为了避免虚拟数据,您只需将值设置为undefined

var foo = function() {
    this.someInstanceMember = undefined;
};

var bar = new foo();

Object.keys(bar)之类的内容会显示someInstanceMemeber已定义,for for循环将获得此"someInstanceMember" in bartrue