簡體   English   中英

遍歷 object 屬性

[英]Iterate through object properties

 var obj = { name: "Simon", age: "20", clothing: { style: "simple", hipster: false } } for(var propt in obj){ console.log(propt + ': ' + obj[propt]); }

變量propt如何表示object的屬性? 它不是內置的方法或屬性。 為什么它會出現 object 中的每個屬性?

迭代屬性需要這個額外的hasOwnProperty檢查:

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

這是必要的,因為對象的原型包含 object 的附加屬性,這些屬性在技術上是 object 的一部分。 這些附加屬性繼承自基礎 object class,但仍然是obj的屬性。

hasOwnProperty只是檢查這是否是特定於此 class 的屬性,而不是從基礎 class 繼承的屬性。


也可以通過 object 本身調用hasOwnProperty

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

但是如果 object 有一個不相關的同名字段,這將失敗:

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 1.8.5 開始,您可以使用Object.keys(obj)來獲取在 objectOwn 本身上定義的屬性數組(返回obj.hasOwnProperty(key)為 true 的 obj 本身的屬性。

Object.keys(obj).forEach(function(key,index) {
    // key: the name of the object key
    // index: the ordinal position of the key within the object 
});

這比使用 for-in 循環更好(並且更具可讀性)。

它在這些瀏覽器上受支持:

  • Firefox(壁虎):4(2.0)
  • 鉻:5
  • 互聯網瀏覽器:9

有關更多信息,請參閱Mozilla 開發人員網絡Object.keys()的參考

我們是 2019 年的女孩和男孩,我們沒有那么多時間打字......所以讓我們來做這個酷炫的新奇特 ECMAScript 2016:

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

這是for...in statementMDNECMAScript 規范)。

您可以將其讀作“對於obj object中的每個屬性,依次將每個屬性分配給PROPT變量”。

在 ES 的最新實現中,您可以使用Object.entries

for (const [key, value] of Object.entries(obj)) { }

或者

Object.entries(obj).forEach(([key, value]) => ...)

如果您只想遍歷這些值,請使用 Object.values:

for (const value of Object.values(obj)) { }

或者

Object.values(obj).forEach(value => ...)

這只是一個for...in循環。 查看Mozilla 的文檔

if (typeof obj === 'object' && obj !== null) {
    Object.keys(obj).forEach(key => {
        console.log("\n" + key + ": " + obj[key]);
    });
}

// *** Explanation line by line ***

// Explaining the bellow line
// It checks if obj is neither null nor undefined, which means it's safe to get its keys. 
// Otherwise it will give you a "TypeError: Cannot convert undefined or null to object" if obj is null or undefined.
// NOTE 1: You can use Object.hasOwnProperty() instead of Object.keys(obj).length
// NOTE 2: No need to check if obj is an array because it will work just fine.
// NOTE 3: No need to check if obj is a string because it will not pass the if typeof obj is Object statement.
// NOTE 4: No need to check if Obj is undefined because it will not pass the if type obj is Object statement either.
if (typeof obj === 'object' && obj !== null) {

    // Explaining the bellow line
    // Just like in the previous line, this returns an array with
    // all keys in obj (because if code execution got here, it means 
    // obj has keys.) 
    // Then just invoke built-in javascript forEach() to loop
    // over each key in returned array and calls a call back function 
    // on each array element (key), using ES6 arrow function (=>)
    // Or you can just use a normal function ((key) { blah blah }).
    Object.keys(obj).forEach(key => {

        // The bellow line prints out all keys with their 
        // respective value in obj.
        // key comes from the returned array in Object.keys(obj)
        // obj[key] returns the value of key in obj
        console.log("\n" + key + ": " + obj[key]);
    });
}

如果您的環境支持ES2017 ,那么我會推薦Object.entries

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

Mozillas Object.entries()文檔所示:

Object.entries()方法返回給定對象自己的可枚舉屬性 [key, value] 對的數組,其順序與 for...in 循環提供的順序相同(不同之處在於 for-in 循環枚舉原型鏈中的屬性)。

基本上使用 Object.entries 我們可以放棄舊的 for...in循環所需的以下額外步驟:

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

多米尼克的回答是完美的,我只是更喜歡這樣做,因為它更容易閱讀:

for (var property in obj) {
    if (!obj.hasOwnProperty(property)) continue;

    // Do stuff...
}

jquery 允許您現在執行此操作:

$.each( obj, function( key, value ) {
  alert( key + ": " + value );
});

for...in 循環表示 object 中的每個屬性,因為它就像一個 for 循環。 您通過執行以下操作在 for...in 循環中定義了 propt:

    for(var propt in obj){
alert(propt + ': ' + obj[propt]);
}

for...in 循環遍歷 object 的可枚舉屬性。 無論您定義或放入 for...in 循環中的哪個變量,每次轉到它迭代的下一個屬性時都會發生變化。 for...in 循環中的變量遍歷鍵,但它的值是鍵的值。 例如:

    for(var propt in obj) {
      console.log(propt);//logs name
      console.log(obj[propt]);//logs "Simon"
    }

您可以看到變量與變量的值有何不同。 相反,for...of 循環則相反。

我希望這有幫助。

添加 ES2015 對Reflect.ownKeys(obj)的使用,並通過迭代器迭代屬性。

例如:

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

可以通過以下方式迭代

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

If you would like to iterate directly over the values of the keys of an object, you can define an iterator , just like JavaScipts's default iterators for strings, arrays, typed arrays, Map and Set.

JS 將嘗試通過默認的迭代器屬性進行迭代,該屬性必須定義為Symbol.iterator

如果您希望能夠遍歷所有對象,您可以將其添加為 Object 的原型:

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

這將使您能夠使用 for...of 循環遍歷 object 的值,例如:

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

注意:在撰寫此答案時(2018 年 6 月),除 IE 外,所有其他瀏覽器都支持生成器和for...of迭代通過Symbol.iterator

let obj = {"a": 3, "b": 2, "6": "a"}

Object.keys(obj).forEach((item) => {console.log("item", obj[item])})

// a
// 3
// 2

上面的答案有點煩人,因為在您確保它是 object 之后,它們沒有解釋您在 for 循環中所做的事情:您不直接訪問它:您實際上只收到了您需要應用於 OBJ 的密鑰

var obj = {
  a: "foo",
  b: "bar",
  c: "foobar"
};

// We need to iterate the string keys (not the objects)
for(var someKey in obj)
{
  // We check if this key exists in the obj
  if (obj.hasOwnProperty(someKey))
  {
    // someKey is only the KEY (string)! Use it to get the obj:
    var myActualPropFromObj = obj[someKey]; // Since dynamic, use [] since the key isn't literally named "someKey"

    // NOW you can treat it like an obj
    var shouldBeBar = myActualPropFromObj.b;
  }
}

這都是 ECMA5 安全的。 甚至可以在像 Rhino 這樣的蹩腳的 JS 版本中工作;)

您可以使用for...inforEach循環訪問 object 的嵌套屬性。

對於...在:

for (const key in info) {
    console.log(info[key]);
}

對於每個:

Object.keys(info).forEach(function(prop) {
    console.log(info[prop]);
    // cities: Array[3], continent: "North America", images: Array[3], name: "Canada"
    // "prop" is the property name
    // "data[prop]" is the property value
});

您可以使用 Lodash。 文檔

var obj = {a: 1, b: 2, c: 3};
_.keys(obj).forEach(function (key) {
    ...
});
Object.keys(obj).forEach(key =>
  console.log(`key=${key} value=${obj[key]}`)
);

現在,您只需添加 Symbol.iterator 方法即可將標准的 JS object 轉換為可迭代的 object。 然后,您可以使用for of循環並直接訪問其值,甚至可以在 object 上使用擴展運算符。 涼爽的。 讓我們看看我們是如何做到的:

 var o = {a:1,b:2,c:3}, a = []; o[Symbol.iterator] = function*(){ var ok = Object.keys(this); i = 0; while (i < ok.length) yield this[ok[i++]]; }; for (var value of o) console.log(value); // or you can even do like a = [...o]; console.log(a);

for循環正在遍歷 object obj的所有屬性。 propt在 for 循環的第一行中定義。 它是一個字符串,它是obj object 的屬性名稱。 在循環的第一次迭代中, propt將是“名稱”。

JavaScript 中的對象是 collections 的屬性,因此可以在每個語句中循環。

您應該將obj視為鍵值集合。

在JavaScript中迭代對象的方式類型

  • 對於...在循環

  • for ... of循環

  • forEach()方法

  • map()方法

 let obj = { city1: 'BOM', city2: 'BLR', city3: 'HYD', state: { city1: 'Sub-city1', city2: 'Sub-city2' } } console.log('----------------using for...in loop------') for(let entry in obj) console.log(entry +" -> "+ obj[entry]) for (var key in obj) { if (obj.hasOwnProperty(key)) { console.log(key + " -> " + obj[key]); } } console.log('----------------using for...of loop------') for (const key of Object.keys(obj)) console.log(key +" -> "+ obj[key]); for (const [key, value] of Object.entries(obj)) console.log(key +" -> "+ value); console.log('----------------using forEach loop------') Object.entries(obj).forEach(([key, value]) => console.log(key +" -> "+ value)); console.log('----------------using map function------') Object.entries(obj).map(([k,v])=> console.log(k+' -> '+v)) 

嵌套對象的迭代方法

 let obj = { city1: 'ALD', city2: 'BLR', city3: 'HYD', state: { city4: 'Sub-city1', city5: 'Sub-city2' } } function nestedObj(obj) { for (let key in obj) { // checking if it's nested to iterate again if (obj.hasOwnProperty(key) && (typeof obj[key] === "object")) { nestedObj(obj[key]) } else { // showing the flat attributes console.log(key + " -> " + obj[key]); } } } nestedObj(obj); 

如果運行Node ,我建議:

Object.keys(obj).forEach((key, index) => {
    console.log(key);
});

雖然評價最高的答案是正確的,但這里有一個替代用例,即如果您正在迭代 object 並希望最終創建一個數組。 使用.map而不是forEach

const newObj = Object.keys(obj).map(el => {
    //ell will hold keys 
   // Getting the value of the keys should be as simple as obj[el]
})

for..in 循環的作用是創建一個新變量(var someVariable),然后將給定 object 的每個屬性一個一個地存儲在這個新變量(someVariable)中。 因此,如果您使用塊 {},您可以迭代。 考慮以下示例。

var obj = {
     name:'raman',
     hobby:'coding',
     planet:'earth'
     };

for(var someVariable in obj) {
  //do nothing..
}

console.log(someVariable); // outputs planet

我想補充上面的答案,因為您可能與 Javascript 有不同的意圖。 A JSON object and a Javascript object are different things, and you might want to iterate through the properties of a JSON object using the solutions proposed above, and then be surprised.

假設你有一個 JSON object 像:

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]);
    }
}

在遍歷prop1prop2以及prop3_1的屬性時,您可能會驚訝地看到控制台記錄了01等。 這些對象是序列,序列的索引是 Javascript 中的 object 的屬性。

遞歸遍歷 JSON object 屬性的更好方法是首先檢查 object 是否是序列:

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]);

            }

     }
}

還添加了遞歸方式:

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"} }); 

在這里,我迭代每個節點並創建有意義的節點名稱。 如果您注意到, instanceOf Array 和 instanceOf Object 幾乎做同樣的事情(在我的應用程序中,我給出了不同的邏輯)

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 的回答的啟發。 但是這個解決方案有更好的性能和更少的歧義

您基本上想遍歷 object 中的每個屬性。

JSFiddle

var Dictionary = {
  If: {
    you: {
      can: '',
      make: ''
    },
    sense: ''
  },
  of: {
    the: {
      sentence: {
        it: '',
        worked: ''
      }
    }
  }
};

function Iterate(obj) {
  for (prop in obj) {
    if (obj.hasOwnProperty(prop) && isNaN(prop)) {
      console.log(prop + ': ' + obj[prop]);
      Iterate(obj[prop]);
    }
  }
}
Iterate(Dictionary);

To further refine the accepted answer it's worth noting that if you instantiate the object with a var object = Object.create(null) then object.hasOwnProperty(property) will tr​​igger a TypeError. 所以為了安全起見,你需要像這樣從原型中調用它:

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

檢查此鏈接將有助於https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_state_forin

var person = {fname:"John", lname:"Doe", age:25}; 

  var text = "";
  var x;
  for (x in person) {
    text += person[x] + " "; // where x will be fname,lname,age
   }
Console.log(text);

檢查類型

您可以通過以下方式檢查 propt 如何表示 object 屬性

typeof propt

發現它只是一個字符串(屬性名稱)。 由於for-in js“內置”循環的工作方式,它提供了 object 中的每個屬性。

 var obj = { name: "Simon", age: "20", clothing: { style: "simple", hipster: false } } for(var propt in obj){ console.log(typeof propt, propt + ': ' + obj[propt]); }

如果您只想迭代到 map 屬性值,那么 lodash 有_.mapValues

 const obj = { a: 2, b: 3 } const res = _.mapValues(obj, v => v * 2) console.log(res)
 <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>

實現這一點的簡單而清晰的方法,即不迭代原型的現代 JS,如下所示:

Object.prototype.iterateProperties = ((callback) => {
   Object.keys(obj).filter(key => obj.hasOwnProperty(key)).forEach((key) => {
      callback(key, obj[key]);
   });
});

解釋

此代碼在所有對象的原型中創建一個函數 - 意味着在每個Object實例中都可以訪問的函數。 該函數迭代對象的所有自己的屬性並運行一個回調函數,該函數為對象中的每個屬性獲取(key, value)

使用示例

obj.iterateProperties((key, value) => console.log(key + ': ' + value));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM