利用Object.keys遍歷(forEach/map)對象數組,合併

js中幾種遍歷對象的方法,包括for..of、for..in、Object.keys、Object.getOwnProperty,它們在使用場景方面各有不一樣。es6

js對象的屬性中可直接用、可訪問到的屬性分爲數據屬性和訪問器屬性。json

數據屬性(實際存儲屬性值的屬性)的四大特性:

{    
    value: 屬性值,    
    writable: true/false,  //控制是否可修改    
    enumerable: true/false, //控制是否可被for in遍歷    
    configurable: true/false, //1. 控制是否可刪除 2. 控制是否可修改前兩個特性  3.一旦改成false不可逆                                                       
}

訪問器屬性(不實際存儲數據,專門提供對其它數據/變量的保護)的四大特性:

{
    get:function(){return this.隱藏屬性;},
    set:function(val){
        //若是val符合條件
            this.隱藏屬性=val
        //不然
            報錯
    },
    enumerable, configurable
}

for..in

返回的是全部可以經過對象訪問的、可枚舉的屬性,既包括存在於實例中的屬性,也包括存在於原型中的實例,不能保證屬性按對象原來的順序輸出。(可枚舉-自身-原型)數組

var obj = {a:1, b:2, c:3};
    
for (var prop in obj) {
  console.log("obj." + prop + " = " + obj[prop]);
}
// Output:
// "obj.a = 1"
// "obj.b = 2"
// "obj.c = 3"

Object.keys

用於獲取對象自身全部的可枚舉的屬性值,但不包括原型中的屬性,而後返回一個由屬性名組成的數組。注意它同for..in同樣不能保證屬性按對象原來的順序輸出。(可枚舉-自身)post

// 數組
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']

// 類數組對象
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']

// 類數組對象-隨機下標
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // console: ['2', '7', '100']

// 不可枚舉屬性getFoo
var myObj = Object.create({}, {
  getFoo: {
    value: function () { return this.foo; }
  } 
});
myObj.foo = 1;
console.log(Object.keys(myObj)); // console: ['foo']

Object.getOwnProperty

若是你想獲取一個對象的全部屬性,甚至包括不可枚舉的,則可用該方法。其返回對象的全部自身屬性的屬性名組成的數組,但不會獲取原型鏈上的屬性。(可枚舉&不可枚舉-自身)this

//獲取不可枚舉屬性
var my_obj = Object.create({}, {
  getFoo: {
    value: function() { return this.foo; },
    enumerable: false
  }
});
my_obj.foo = 1;

console.log(Object.getOwnPropertyNames(my_obj).sort()); // ["foo", "getFoo"]

下面的例子演示了該方法不會獲取到原型鏈上的屬性:spa

function ParentClass() {}
ParentClass.prototype.inheritedMethod = function() {};

function ChildClass() {
  this.prop = 5;
  this.method = function() {};
}

ChildClass.prototype = new ParentClass;
ChildClass.prototype.prototypeMethod = function() {};

console.log(
  Object.getOwnPropertyNames(
    new ChildClass()  // ["prop", "method"]
  )
);

for..of

es6新增方法,主要來遍歷可迭代的對象(包括Array, Map, Set, arguments等),它主要用來獲取對象value值,而for..in主要獲取對象key值。
另外:能夠由break, continue, throw 或return終止。在這些狀況下,迭代器關閉。prototype

let iterable = [10, 20, 30];
for (let value of iterable) {
    value += 1;
    console.log(value);
}
// 11
// 21
// 31

與for..in循環之間的區別:code

Object.prototype.objCustom = function() {}; 
Array.prototype.arrCustom = function() {};

let iterable = [3, 5, 7];
iterable.foo = 'hello';

for (let i in iterable) {
  console.log(i); //  0, 1, 2, "foo", "arrCustom", "objCustom"
}

for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); //  0, 1, 2, "foo"
  }
}

for (let i of iterable) {
  console.log(i); //  3, 5, 7
}

小結

其實這幾個方法之間的差別主要在屬性是否可可枚舉,是來自原型,仍是實例。
圖片描述對象

開發中的實際應用

需求:將以下兩個從後臺不一樣端口獲取的json對象數組整合處理成以下注釋部分的json對象圖片

var goodsSpecJSON = [{
                "SpecA": "顏色"
            }, {
                "SpecB": "容量"
            }, {
                "SpecC": "大小"
            }, {
                "SpecD": "尺寸"
            }, {
                "SpecE": "套餐"
            }];
var goodsSpecList = [{
    c_id: 3133,
    costPrice: 0,
    discountPrice: 0,
    earn: 0,
    etime: null,
    flag: 0,
    goodsDetailCount: 199,
    goodsDetailId: "100PgQ2xy08121409mY27",
    goodsDetailInventory: 199,
    goodsDetailOff: 0,
    goodsDetailPic: "/upload/messageImage/1523281057461_Personal.jpg,/upload/messageImage/1523282906972_Personal.jpg,/upload/messageImage/1523283570897_Personal.jpg",
    goodsDetailPrice: 188,
    goodsDetailSpec: "",
    goodsId: "00Y1kR4r1029X822731o0",
    isHost: 0,
    managerEarn: 0,
    postage: 10,
    profit: 0,
    specA: "紅色",
    specB: "32G",
    specC: "小",
    specD: "4.7寸",
    specE: "套餐一",
    unionEarn: 0,
    vipPrice: 0
}, {
    c_id: 3134,
    costPrice: 0,
    discountPrice: 0,
    earn: 0,
    etime: null,
    flag: 0,
    goodsDetailCount: 199,
    goodsDetailId: "100PgQ2xy08121409mY27",
    goodsDetailInventory: 199,
    goodsDetailOff: 0,
    goodsDetailPic: "/upload/messageImage/1523281057461_Personal.jpg,/upload/messageImage/1523282906972_Personal.jpg,/upload/messageImage/1523283570897_Personal.jpg",
    goodsDetailPrice: 188,
    goodsDetailSpec: "",
    goodsId: "00Y1kR4r1029X822731o0",
    isHost: 0,
    managerEarn: 0,
    postage: 10,
    profit: 0,
    specA: "白色",
    specB: "64G",
    specC: "小",
    specD: "5寸",
    specE: "套餐二",
    unionEarn: 0,
    vipPrice: 0
}, {
    c_id: 3135,
    costPrice: 0,
    discountPrice: 0,
    earn: 0,
    etime: null,
    flag: 0,
    goodsDetailCount: 199,
    goodsDetailId: "100PgQ2xy08121409mY27",
    goodsDetailInventory: 199,
    goodsDetailOff: 0,
    goodsDetailPic: "/upload/messageImage/1523281057461_Personal.jpg,/upload/messageImage/1523282906972_Personal.jpg,/upload/messageImage/1523283570897_Personal.jpg",
    goodsDetailPrice: 188,
    goodsDetailSpec: "",
    goodsId: "00Y1kR4r1029X822731o0",
    isHost: 0,
    managerEarn: 0,
    postage: 10,
    profit: 0,
    specA: "黑色",
    specB: "128G",
    specC: "小",
    specD: "4.7寸",
    specE: "套餐一",
    unionEarn: 0,
    vipPrice: 0
}, {
    c_id: 3136,
    costPrice: 0,
    discountPrice: 0,
    earn: 0,
    etime: null,
    flag: 0,
    goodsDetailCount: 199,
    goodsDetailId: "100PgQ2xy08121409mY27",
    goodsDetailInventory: 199,
    goodsDetailOff: 0,
    goodsDetailPic: "/upload/messageImage/1523281057461_Personal.jpg,/upload/messageImage/1523282906972_Personal.jpg,/upload/messageImage/1523283570897_Personal.jpg",
    goodsDetailPrice: 188,
    goodsDetailSpec: "",
    goodsId: "00Y1kR4r1029X822731o0",
    isHost: 0,
    managerEarn: 0,
    postage: 10,
    profit: 0,
    specA: "藍色",
    specB: "64GG",
    specC: "大",
    specD: "4.5寸",
    specE: "套餐二",
    unionEarn: 0,
    vipPrice: 0
}];

// var keys = {
//     '顏色': ['紅色', '白色'],
//     '容量': ['8g', '16g', '32g', '64g'],
//     '尺寸': ['大', '小', '大'],
//     '套餐': ['套餐一', '套餐二', '套餐三']
// };
// //SKU,Stock Keeping Uint(庫存量單位)    
// var sku_list = [{
//     'attrs': '紅色|16g|big|套餐二',
//     'price': 120
// }, {
//     'attrs': '紅色|8g|big|套餐一',
//     'price': 10
// }, {
//     'attrs': '白色|16g|big|套餐二',
//     'price': 28
// }, {
//     'attrs': '紅色|64g|small|套餐三',
//     'price': 220
// }, {
//     'attrs': '白色|32g|middle|套餐二',
//     'price': 130
// }, {
//     'attrs': '紅色|32g|big|套餐一',
//     'price': 120
// }, ];

實現:主要利用Object.keys方法獲取對象的key,value值,配上forEach循環實現最終想要的結果。

var keys = {};
var sku_list = [];
//原數據轉換小寫
goodsSpecJSON = goodsSpecJSON.map(function (keyo) {
    var key = Object.keys(keyo)[0];
    var newkey = key.substring(0, 1).toLowerCase() + key.substring(1);
    var dic = {};
    dic[newkey] = keyo[key];
    return dic
});
//生成keys
goodsSpecJSON.forEach(function (keyo) {
    var key = Object.keys(keyo)[0]; //['specA']
    var val = keyo[key]; //顏色
    if (!keys.hasOwnProperty(val)) {
        keys[val] = [];
    }
    var hash = {};
    goodsSpecList.forEach(function (item, i) {
        if (hash[item[key]] === undefined) {
            hash[item[key]] = true;
            keys[val].push(item[key]);
        }
        // if (keys[val].indexOf(item[key]) === -1) {
        //     keys[val].push(item[key]);
        // }
    });
});
console.log(keys)
//生成sku_list
goodsSpecList.forEach(function (item) {
    var dic = {
        attrs: ''
    };
    goodsSpecJSON.forEach(function (keyo, j) {
        var key = Object.keys(keyo)[0];
        dic.attrs += item[key] + (j === goodsSpecJSON.length - 1 ? '' : '|');
        dic.price = item.goodsDetailPrice;
        dic.goodsDetailCount = item.goodsDetailCount;
        dic.goodsDetailId = item.goodsDetailId;
    });
    sku_list.push(dic);
});
console.log(sku_list)

輸出結果:
圖片描述

相關文章
相關標籤/搜索