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

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


当前回答

我想补充上面的答案,因为您可能与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]);

            }
            
     }
}

其他回答

这是为了。。。in语句(MDN、ECMAScript规范)。

您可以将其读为“对于obj对象中的每个属性,依次将每个属性分配给PROPT变量”。

迭代财产需要额外的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

添加ES2015对Reflect.ownKeys(obj)的使用,并通过迭代器迭代财产。

例如:

let obj = { a: 'Carrot', b: 'Potato', Car: { doors: 4 } };

可以通过

// logs each key
Reflect.ownKeys(obj).forEach(key => console.log(key));

如果您想直接迭代对象的键的值,可以定义迭代器,就像JavaScipts的字符串、数组、类型化数组、Map和Set的默认迭代器一样。

JS将尝试通过默认迭代器属性进行迭代,该属性必须定义为Symbol.iterator。

如果希望能够遍历所有对象,可以将其添加为Object的原型:

Object.prototype[Symbol.iterator] = function*() { 
    for(p of Reflect.ownKeys(this)){ yield this[p]; }
}

这将使您能够使用for。。。例如:

for(val of obj) { console.log('Value is:' + val ) }

注意:截至撰写此答案(2018年6月),除IE外,所有其他浏览器都支持生成器和。。。通过Symbol.iterator迭代

在这里,我迭代每个节点并创建有意义的节点名称。如果您注意到,instanceOfArray和instanceOfObject几乎做了相同的事情(在我的应用程序中,我给出了不同的逻辑)

function iterate(obj,parent_node) {
    parent_node = parent_node || '';
    for (var property in obj) {
        if (obj.hasOwnProperty(property)) {
            var node = parent_node + "/" + property;
            if(obj[property] instanceof Array) {
                //console.log('array: ' + node + ":" + obj[property]);
                iterate(obj[property],node)
            } else if(obj[property] instanceof Object){
                //console.log('Object: ' + node + ":" + obj[property]);
                iterate(obj[property],node)
            }
            else {
                console.log(node + ":" + obj[property]);
            }
        }
    }
}

注:我受到了翁德雷·斯文达尔(Ondrej Svejdar)的回答的启发。但此解决方案具有更好的性能和更少的模糊性

这只是为了。。。在循环中。查看Mozilla的文档。