变量obj={name:“西蒙”,年龄:“20”,服装:{style:“简单”,嬉皮士:假}}for(obj中的var propt){console.log(propt+':'+obj[propt]);}

变量propt如何表示对象的财产?它不是内置方法或属性。为什么它会产生对象中的每个属性?


当前回答

如果您的环境支持ES2017,那么我将推荐Object.entries:

Object.entries(obj).forEach(([key, value]) => {
  console.log(`${key} ${value}`);
});

如Mozillas Object.entries()文档所示:

Object.entries()方法返回给定对象自身的数组可枚举属性[key,value]对,顺序与由…提供。。。in循环(区别在于for in循环还列举了原型链中的财产)。

基本上,使用Object.entries,我们可以放弃旧的for。。。循环中:

// This step is not necessary with Object.entries
if (object.hasOwnProperty(property)) {
  // do stuff
}

其他回答

迭代财产需要额外的hasOwnProperty检查:

for (var prop in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, prop)) {
        // do stuff
    }
}

这是必要的,因为对象的原型包含对象的附加财产,这些属性在技术上是对象的一部分。这些附加的财产继承自基本对象类,但仍然是obj的财产。

hasOwnProperty只是检查这是否是该类特有的属性,而不是从基类继承的属性。


也可以通过对象本身调用hasOwnProperty:

if (obj.hasOwnProperty(prop)) {
    // do stuff
}

但如果对象具有同名的不相关字段,则此操作将失败:

var obj = { foo: 42, hasOwnProperty: 'lol' };
obj.hasOwnProperty('foo');  // TypeError: hasOwnProperty is not a function

这就是为什么通过Object.prototype调用它更安全的原因:

var obj = { foo: 42, hasOwnProperty: 'lol' };
Object.prototype.hasOwnProperty.call(obj, 'foo');  // true

JavaScript中的对象是财产的集合,因此可以在for-each语句中循环。

您应该将obj视为键值集合。

我想补充上面的答案,因为您可能与Javascript有不同的意图。JSON对象和Javascript对象是不同的东西,您可能想使用上面提出的解决方案迭代JSON对象的财产,然后感到惊讶。

假设您有一个JSON对象,如:

var example = {
    "prop1": "value1",
    "prop2": [ "value2_0", "value2_1"],
    "prop3": {
         "prop3_1": "value3_1"
    }
}

迭代其“财产”的错误方式:

function recursivelyIterateProperties(jsonObject) {
    for (var prop in Object.keys(example)) {
        console.log(prop);
        recursivelyIterateProperties(jsonObject[prop]);
    }
}

迭代prop1、prop2和prop3_1的财产时,您可能会惊讶地看到控制台记录0、1等。这些对象是序列,序列的索引是Javascript中该对象的财产。

递归迭代JSON对象财产的更好方法是首先检查该对象是否为序列:

function recursivelyIterateProperties(jsonObject) {
    for (var prop in Object.keys(example)) {
        console.log(prop);
        if (!(typeof(jsonObject[prop]) === 'string')
            && !(jsonObject[prop] instanceof Array)) {
                recursivelyIterateProperties(jsonObject[prop]);

            }
            
     }
}

for循环遍历对象的所有财产。propt在for循环的第一行中定义。它是一个字符串,是obj对象的属性的名称。在循环的第一次迭代中,propt将是“name”。

还添加了递归方式:

function iterate(obj) {
    // watch for objects we've already iterated so we won't end in endless cycle
    // for cases like var foo = {}; foo.bar = foo; iterate(foo);
    var walked = [];
    var stack = [{obj: obj, stack: ''}];
    while(stack.length > 0)
    {
        var item = stack.pop();
        var obj = item.obj;
        for (var property in obj) {
            if (obj.hasOwnProperty(property)) {
                if (typeof obj[property] == "object") {
                  // check if we haven't iterated through the reference yet
                  var alreadyFound = false;
                  for(var i = 0; i < walked.length; i++)
                  {
                    if (walked[i] === obj[property])
                    {
                      alreadyFound = true;
                      break;
                    }
                  }
                  // new object reference
                  if (!alreadyFound)
                  {
                    walked.push(obj[property]);
                    stack.push({obj: obj[property], stack: item.stack + '.' + property});
                  }
                }
                else
                {
                    console.log(item.stack + '.' + property + "=" + obj[property]);
                }
            }
        }
    }
}

用法:

iterate({ foo: "foo", bar: { foo: "foo"} });