Как выполнить цикл или перечислить объект JavaScript?

У меня есть JavaScript-объект, например:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Теперь я хочу перебрать все элементы p (p1, p2, p3...) и получить их ключи и значения. Как я могу это сделать?

При необходимости я могу изменить объект JavaScript. Моя конечная цель состоит в том, чтобы перебрать некоторые пары ключевых значений и, если возможно, я хочу избежать использования eval.

Ответ 1

Вы можете использовать цикл for-in, как показано другими. Однако вы также должны убедиться, что ключ, который вы получаете, является фактическим свойством объекта и не исходит от прототипа.

Вот фрагмент:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " -> " + p[key]);
    }
}

Ответ 2

В ECMAScript 5 вы можете объединить Object.keys() и Array.prototype.forEach():

var obj = { first: "John", last: "Doe" };

Object.keys(obj).forEach(function(key) {
    console.log(key, obj[key]);
});

ECMAScript 6 добавляет for...of:

for (const key of Object.keys(obj)) {
    console.log(key, obj[key]);
}

ECMAScript 8 добавляет Object.entries() который избегает необходимости искать каждое значение в исходном объекте:

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

Вы можете комбинировать for...of, destructuring и Object.entries:

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

Оба Object.keys() и Object.entries() повторяют свойства в том же порядке, что и цикл for...in но игнорируют цепочку прототипов. Перечисляются только собственные перечисляемые свойства объекта.

Ответ 3

Вы должны использовать для цикла

Но будьте очень осторожны при использовании этого типа цикла, потому что это будет зацикливать все свойства вдоль цепи прототипа.

Поэтому при использовании for-in циклов всегда используйте метод hasOwnProperty, чтобы определить, действительно ли текущее свойство в итерации является свойством объекта, который вы проверяете:

for (var prop in p) {
    if (!p.hasOwnProperty(prop)) {
        //The current property is not a direct property of p
        continue;
    }
    //Do your logic with the property here
}

Ответ 4

Вопрос не будет завершен, если мы не упомянем об альтернативных методах для прокрутки объектов.

В настоящее время многие известные библиотеки JavaScript предоставляют свои собственные методы для итерации над коллекциями, то есть над массивами, объектами и объектами, подобными массивам. Эти методы удобны в использовании и полностью совместимы с любым браузером.

  • Если вы работаете с jQuery, вы можете использовать метод jQuery.each(). Его можно использовать для беспрепятственной итерации по обоим объектам и массивам:

    $.each(obj, function(key, value) {
        console.log(key, value);
    });
    
  • В Underscore.js вы можете найти метод _.each(), который выполняет итерацию по списку элементов, каждый из которых приводит к поставленной функции (обратите внимание на порядок аргументов в функции iteratee!):

    _.each(obj, function(value, key) {
        console.log(key, value);
    });
    
  • Lo-Dash предоставляет несколько методов для итерации поверх свойств объекта. Basic _.forEach() (или его псевдоним _.each()) полезен для прокрутки объектов и массивов, однако (!) Объектов с length свойство обрабатываются как массивы, и для избежания такого поведения предлагается использовать _.forIn() и _.forOwn() (у них также есть аргумент value):

    _.forIn(obj, function(value, key) {
        console.log(key, value);
    });
    

    _.forIn() выполняет итерацию над собственными и унаследованными перечислимыми свойствами объекта, тогда как _.forOwn() выполняет итерацию только по собственным свойствам объекта (в основном проверяя функцию hasOwnProperty). Для простых объектов и литералов объектов любой из этих методов будет работать нормально.

Как правило, все описанные методы имеют одинаковое поведение с любыми поставленными объектами. Кроме того, использование встроенного цикла for..in обычно будет быстрее, чем любая абстракция, например jQuery.each(), эти методы значительно проще в использовании, требуют меньше кодирования и обеспечивают лучшую обработку ошибок.

Ответ 5

В ECMAScript 5 у вас есть новый подход в итерационных полях буквального - Object.keys

Более подробную информацию вы можете найти на MDN

Мой выбор ниже как более быстрое решение в текущих версиях браузеров (Chrome30, IE10, FF25)

var keys = Object.keys(p),
    len = keys.length,
    i = 0,
    prop,
    value;
while (i < len) {
    prop = keys[i];
    value = p[prop];
    i += 1;
}

Вы можете сравнить производительность этого подхода с различными реализациями на jsperf.com:

Поддержка браузера вы можете увидеть на таблице сопоставления Kangax

Для старого браузера вы просто и full polyfill

UPD:

сравнение производительности для всех наиболее популярных случаев в этом вопросе на perfjs.info:

литеральная итерация объекта

Ответ 6

Вы можете просто перебрать его, например:

for (var key in p) {
  alert(p[key]);
}

Обратите внимание, что key не будет принимать значение свойства, это просто значение индекса.

Ответ 7

Предисловие:

  • Свойства объекта могут быть собственными (свойство находится на самом объекте) или наследоваться (не на самом объекте, на одном из его прототипов).
  • Свойства объекта могут быть перечисляемыми или не перечисляемыми. Неперечислимые свойства исключаются из множества перечислений/массивов свойств.
  • Имена свойств могут быть строками или символами. Свойства, имена которых являются символами, исключаются из множества перечислений/массивов свойств.

Здесь, в 2018 году, ваши варианты циклического просмотра свойств объекта (некоторые примеры следуют за списком):

  1. for-in [ MDN, spec ] - структура цикла, которая перебирает имена перечисляемых свойств объекта, включая унаследованные, имена которых являются строками
  2. Object.keys [ MDN, spec ] - функция, предоставляющая массив имен объектов, обладающих перечисляемыми свойствами, имена которых являются строками.
  3. Object.values [ MDN, spec ] - функция, предоставляющая массив значений объекта, обладающего перечисляемыми свойствами.
  4. Object.entries [ MDN, spec ] - функция, предоставляющая массив имен и значений собственных, перечислимых свойств объекта (каждая запись в массиве является массивом [name, value]).
  5. Object.getOwnPropertyNames [ MDN, spec ] - Функция, предоставляющая массив имен собственных свойств объекта (даже не перечисляемых), имена которых являются строками.
  6. Object.getOwnPropertySymbols [ MDN, spec ] - Функция, предоставляющая массив имен собственных свойств объекта (даже не перечисляемых), чьи имена являются символами.
  7. Reflect.ownKeys [ MDN, spec ] - функция, предоставляющая массив имен собственных свойств объекта (даже не перечисляемых), независимо от того, являются ли эти имена строками или символами.
  8. Если вы хотите, чтобы все свойства объекта, включая не перечисляемые унаследованные, вам необходимо использовать цикл и Object.getPrototypeOf [ MDN, spec ] и использовать Object.getOwnPropertyNames, Object.getOwnPropertySymbols или Reflect.ownKeys для каждого объекта в цепочка прототипов (пример внизу этого ответа).

Со всеми из них, кроме for-in, вы бы использовали некоторую циклическую конструкцию массива (for, for-of, forEach и т.д.).

Примеры:

for-in :

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from 'p'
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name in o) {
    const value = o[name];
    console.log('${name} = ${value}');
}

Ответ 8

Так как es2015 становится все более популярным, я отправляю этот ответ, который включает использование генератора и итератора для плавной итерации через пары [key, value]. Как это возможно в других языках, например Ruby.

Хорошо вот код:

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
  [Symbol.iterator]: function* () {
    for (const i of Object.keys(this)) {
      yield [i, this[i]];
    }
  }
};

for (const [k, v] of MyObject) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

Вся информация о том, как вы можете сделать итератор и генератор, вы можете найти на странице разработчика Mozilla.

Надеюсь, это помогло кому-то.

EDIT:

ES2017 будет включать Object.entries, что упростит итерацию над парами [key, value] в объектах. Теперь известно, что он будет частью стандарта в соответствии с информацией этапа ts39.

Я думаю, что пришло время обновить мой ответ, чтобы он стал еще более свежим, чем сейчас.

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
};

for (const [k, v] of Object.entries(MyObject)) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

Подробнее об использовании страница MDN

Ответ 9

for(key in p) {
  alert( p[key] );
}

Примечание: вы можете делать это по массивам, но вы будете перебирать и теги length и другие свойства.

Ответ 10

После просмотра всех ответов здесь hasOwnProperty не требуется для моего собственного использования, потому что мой json-объект чист; нет смысла добавлять дополнительную обработку javascript. Это все, что я использую:

for (var key in p) {
    console.log(key + ' => ' + p[key]);
    // key is key
    // value is p[key]
}

Ответ 11

через прототип с forEach(), который должен пропустить свойства прототипа цепи:

Object.prototype.each = function(f) {
    var obj = this
    Object.keys(obj).forEach( function(key) { 
        f( key , obj[key] ) 
    });
}


//print all keys and values
var obj = {a:1,b:2,c:3}
obj.each(function(key,value) { console.log(key + " " + value) });
// a 1
// b 2
// c 3

Ответ 12

Интересные люди в этих ответах затронули оба Object.keys() и for...of но никогда не комбинировали их:

var map = {well:'hello', there:'!'};
for (let key of Object.keys(map))
    console.log(key + ':' + map[key]);

Вы не можете просто for...of Object потому что это не итератор, а for...index или .forEach() Object.keys() является уродливым/неэффективным.
Я рад, что большинство людей воздерживаются от for...in (с проверкой или без проверки .hasOwnProperty()), так как это тоже немного грязно, поэтому, кроме моего ответа выше, я здесь, чтобы сказать...


Вы можете сделать обычные ассоциации объектов итерации! Поведение так же, как Map с прямым использованием фантазии for...of
DEMO работает в Chrome и FF (я предполагаю только ES6)

var ordinaryObject = {well:'hello', there:'!'};
for (let pair of ordinaryObject)
    //key:value
    console.log(pair[0] + ':' + pair[1]);

//or
for (let [key, value] of ordinaryObject)
    console.log(key + ':' + value);

Пока вы включаете мой прокладку ниже:

//makes all objects iterable just like Maps!!! YAY
//iterates over Object.keys() (which already ignores prototype chain for us)
Object.prototype[Symbol.iterator] = function() {
    var keys = Object.keys(this)[Symbol.iterator]();
    var obj = this;
    var output;
    return {next:function() {
        if (!(output = keys.next()).done)
            output.value = [output.value, obj[output.value]];
        return output;
    }};
};

Без создания реального объекта Map, который не имеет приятного синтаксического сахара.

var trueMap = new Map([['well', 'hello'], ['there', '!']]);
for (let pair of trueMap)
    console.log(pair[0] + ':' + pair[1]);

На самом деле, с этой прокладкой, если вы все еще хотели воспользоваться преимуществами Map других функций (без обрезки их всех), но все же хотели использовать аккуратную нотацию объекта, так как объекты теперь итерабельны, теперь вы можете просто сделать карту из нее!

//shown in demo
var realMap = new Map({well:'hello', there:'!'});

Для тех, кто не любит прокладку или вообще не работает с prototype вообще, не стесняйтесь делать функцию в окне, вместо этого называя ее чем-то вроде getObjIterator() ;

//no prototype manipulation
function getObjIterator(obj) {
    //create a dummy object instead of adding functionality to all objects
    var iterator = new Object();

    //give it what the shim does but as its own local property
    iterator[Symbol.iterator] = function() {
        var keys = Object.keys(obj)[Symbol.iterator]();
        var output;

        return {next:function() {
            if (!(output = keys.next()).done)
                output.value = [output.value, obj[output.value]];
            return output;
        }};
    };

    return iterator;
}

Теперь вы можете просто называть его обычной функцией, ничто другое не затрагивается

var realMap = new Map(getObjIterator({well:'hello', there:'!'}))

или же

for (let pair of getObjIterator(ordinaryObject))

Нет причин, почему это не сработает.

Добро пожаловать в будущее.

Ответ 13

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " = " + p[key]);
    }
}
<p>
  Output:<br>
  p1 = values1<br>
  p2 = values2<br>
  p3 = values3
</p>

Ответ 14

Object.keys(obj): массив

извлекает все строковые ключи всех перечислимых собственных (не наследуемых) свойств.

Таким образом, он дает тот же список ключей, что и вы, путем тестирования каждого ключа объекта с помощью hasOwnProperty. Вам не нужна эта дополнительная тестовая операция, а не Object.keys( obj ).forEach(function( key ){}) должна быть быстрее. Докажем это:

var uniqid = function(){
			var text = "",
					i = 0,
					possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
			for( ; i < 32; i++ ) {
					text += possible.charAt( Math.floor( Math.random() * possible.length ) );
			}
			return text;
		}, 
		CYCLES = 100000,
		obj = {}, 
		p1,
		p2,
		p3,
		key;

// Populate object with random properties
Array.apply( null, Array( CYCLES ) ).forEach(function(){
	obj[ uniqid() ] = new Date()
});

// Approach #1
p1 = performance.now();
Object.keys( obj ).forEach(function( key ){
	var waste = obj[ key ];
});

p2 = performance.now();
console.log( "Object.keys approach took " + (p2 - p1) + " milliseconds.");

// Approach #2
for( key in obj ) {
	if ( obj.hasOwnProperty( key ) ) {
		var waste = obj[ key ];
	}
}

p3 = performance.now();
console.log( "for...in/hasOwnProperty approach took " + (p3 - p2) + " milliseconds.");

Ответ 15

Вот еще один метод для итерации объекта.

   var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};


Object.keys(p).forEach(key => { console.log(key, p[key]) })

Ответ 16

Метод Object.keys() возвращает массив заданных объектов для собственных перечислимых свойств. Подробнее об этом здесь

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Object.keys(p).map((key)=> console.log(key + "->" + p[key]))

Ответ 17

Вы можете добавить простую функцию forEach ко всем объектам, чтобы вы могли автоматически прокручивать любой объект:

Object.defineProperty(Object.prototype, 'forEach', {
    value: function (func) {
        for (var key in this) {
            if (!this.hasOwnProperty(key)) {
                // skip loop if the property is from prototype
                continue;
            }
            var value = this[key];
            func(key, value);
        }
    },
    enumerable: false
});

Для тех людей, которым не нравится "for... in" -method:

Object.defineProperty(Object.prototype, 'forEach', {
    value: function (func) {
        var arr = Object.keys(this);
        for (var i = 0; i < arr.length; i++) {
            var key = arr[i];
            func(key, this[key]);
        }
    },
    enumerable: false
});

Теперь вы можете просто позвонить:

p.forEach (function(key, value){
    console.log ("Key: " + key);
    console.log ("Value: " + value);
});

Если вы не хотите создавать конфликты с другими forEach-методами, вы можете назвать его своим уникальным именем.

Ответ 18

Только код JavaScript без зависимостей:

var p = {"p1": "value1", "p2": "value2", "p3": "value3"};
keys = Object.keys(p);   // ["p1", "p2", "p3"]

for(i = 0; i < keys.length; i++){
  console.log(keys[i] + "=" + p[keys[i]]);   // p1=value1, p2=value2, p3=value3
}

Ответ 19

Циклы могут быть довольно интересными при использовании чистого JavaScript. Похоже, что только ECMA6 (спецификация JavaScript для нового 2015 года) получил контроль над циклами. К сожалению, поскольку я пишу это, оба браузера и популярная интегрированная среда разработки (IDE) по-прежнему изо всех сил пытаются полностью поддержать новые колокола и свистки.

На первый взгляд, вот как выглядит цикл JavaScript JavaScript перед ECMA6:

for (var key in object) {
  if (p.hasOwnProperty(key)) {
    var value = object[key];
    console.log(key); // This is the key;
    console.log(value); // This is the value;
  }
}

Кроме того, я знаю, что этот вопрос выходит за рамки этого вопроса, но в 2011 году ECMAScript 5.1 добавил только метод forEach для массивов, который в основном создавал новый улучшенный способ циклического преобразования массивов при сохранении неизменяемых объектов со старым многословный и запутанный цикл for. Но странная часть заключается в том, что этот новый метод forEach не поддерживает break, что приводит к возникновению всех других проблем.

В принципе, в 2011 году не существует реального надежного способа для цикла в JavaScript, кроме того, что многие популярные библиотеки (jQuery, Underscore и т.д.) решили повторно реализовать.

Начиная с 2015 года, теперь у нас есть лучший способ использовать цикл (и разбивать) любой тип объекта (включая массивы и строки). Вот как будет выглядеть цикл в JavaScript, когда рекомендация станет основной:

for (let [key, value] of Object.entries(object)) {
    console.log(key); // This is the key;
    console.log(value); // This is the value;
}

Обратите внимание, что большинство браузеров не будут поддерживать указанный выше код с 18 июня 2016 года. Даже в Chrome вам нужно включить этот специальный флаг для его работы: chrome://flags/#enable-javascript-harmony

Пока это не станет новым стандартом, старый метод все еще можно использовать, но есть альтернативы в популярных библиотеках или даже облегченные альтернативы для тех которые не используют ни одну из этих библиотек.

Ответ 20

    var p =[{"username":"ordermanageadmin","user_id":"2","resource_id":"Magento_Sales::actions"},
{"username":"ordermanageadmin_1","user_id":"3","resource_id":"Magento_Sales::actions"}]
for(var value in p) {
    for (var key in value) {
        if (p.hasOwnProperty(key)) {
            console.log(key + " -> " + p[key]);
        }
    }
}

Ответ 21

Вы также можете использовать Object.keys() и перебирать ключи объекта, как показано ниже, чтобы получить значение:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Object.keys(p).forEach((key)=> {
 console.log(key +' -> '+ p[key]);
});

Ответ 22

Я сделал бы это вместо проверки obj.hasOwnerProperty в каждом цикле for ... in.

var obj = {a : 1};
for(var key in obj){
    //obj.hasOwnProperty(key) is not needed.
    console.log(key);
}
//then check if anybody has messed the native object. Put this code at the end of the page.
for(var key in Object){
    throw new Error("Please don't extend the native object");
}

Ответ 23

Если кому-то нужно выполнить цикл через arrayObjects с условием:

var arrayObjects = [{"building":"A", "status":"good"},{"building":"B","status":"horrible"}];

for (var i=0; i< arrayObjects.length; i++) {
  console.log(arrayObjects[i]);
  
  for(key in arrayObjects[i]) {      
    
      if (key == "status" && arrayObjects[i][key] == "good") {
        
          console.log(key + "->" + arrayObjects[i][key]);
      }else{
          console.log("nothing found");
      }
   }
}

Ответ 24

Учитывая ES6, я хотел бы добавить свою собственную ложку сахара и предложить еще один подход к итерации по свойствам объекта.

Поскольку простой объект JS не является iterable просто из коробки, мы не можем использовать цикл for..of для итерации по его содержание. Но никто не может остановить нас , чтобы сделать его итерируемым.

Пусть у нас есть объект book.

let book = {
  title: "Amazing book",
  author: "Me",
  pages: 3
}

book[Symbol.iterator] = function(){

  let properties = Object.keys(this); // returns an array with property names
  let counter = 0;
  let isDone = false;

  let next = () => {
    if(counter >= properties.length){
      isDone = true;
    }
    return { done: isDone, value: this[properties[counter++]] }
  }

  return { next };
}

Поскольку мы сделали это, мы можем использовать его следующим образом:

for(let pValue of book){
  console.log(pValue);
}
------------------------
Amazing book
Me
3

Или, если вы знаете силу генераторов ES6 поэтому вы наверняка можете сделать код намного короче.

book[Symbol.iterator] = function *(){

  let properties = Object.keys(this);
  for (let p of properties){
    yield this[p];
  }

}

Конечно, вы можете применить такое поведение для всех объектов, сделав Object iterable на уровне prototype.

Object.prototype[Symbol.iterator] = function() {...}

Кроме того, объекты, которые соответствуют итерабельному протоколу, могут использоваться с новой функцией ESa015 spread, поэтому мы можем читать значения свойств объекта как массив.

let pValues = [...book];
console.log(pValues);
-------------------------
["Amazing book", "Me", 3]

Или вы можете использовать destructuring назначение:

let [title, , pages] = book; // notice that we can just skip unnecessary values
console.log(title);
console.log(pages);
------------------
Amazing book
3

Вы можете проверить JSFiddle со всем приведенным выше кодом.

Ответ 25

В ES6 у нас есть хорошо известные символы, чтобы разоблачить некоторые ранее внутренние методы, вы можете использовать его для определения того, как итераторы работают для этого объекта:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3",
    *[Symbol.iterator]() {
        yield *Object.keys(this);
    }
};

[...p] //["p1", "p2", "p3"]

это даст тот же результат, что и использование для... в цикле es6.

for(var key in p) {
    console.log(key);
}

Но важно знать, какие возможности у вас есть с помощью es6!

Ответ 26

начиная с ES06, вы можете получить значения объекта в виде массива с

let arrValues = Object.values( yourObject) ;

он возвращает массив значений объекта и не извлекает значения из Prototype !!

MDN DOCS Object.values()

и для ключей (уже ответили до меня здесь)

let arrKeys   = Object.keys(yourObject);

Ответ 27

Если вы хотите перебрать неперечислимые свойства, вы можете использовать Object.getOwnPropertyNames(obj), чтобы вернуть массив всех свойств (перечисляемых или нет), найденных непосредственно на заданный объект.

var obj = Object.create({}, {
  // non-enumerable property
  getFoo: {
    value: function() { return this.foo; },
    enumerable: false
  }
});

obj.foo = 1; // enumerable property

Object.getOwnPropertyNames(obj).forEach(function (name) {
  document.write(name + ': ' + obj[name] + '<br/>');
});

Ответ 28

В последнем сценарии ES вы можете сделать что-то вроде этого:

Object.entries(p);

Ответ 29

Object.entries():

var p = {
	    "p1": "value1",
	    "p2": "value2",
	    "p3": "value3"
	};

for (var i in Object.entries(p)){
	var key = Object.entries(p)[i][0];
	var value = Object.entries(p)[i][1];
	console.log('key['+i+']='+key+' '+'value['+i+']='+value);
}

Ответ 30

У меня была аналогичная проблема при использовании Angular, вот решение, которое я нашел.

Шаг 1. Получить все ключи объектов. используя Object.keys. Этот метод возвращает массив заданных объектов собственных перечислимых свойств.

Шаг 2. Создайте пустой массив. Это место, где все свойства будут жить, так как ваш новый цикл ngFor будет указывать на этот массив, мы должны поймать их всех. Шаг 3.. Итерации бросают все ключи и нажимают каждый в массив, который вы создали. Вот как это выглядит в коде.

    // Evil response in a variable. Here are all my vehicles.
let evilResponse = { 
  "car" : 
    { 
       "color" : "red",
       "model" : "2013"
    },
   "motorcycle": 
    { 
       "color" : "red",
       "model" : "2016"
    },
   "bicycle": 
    { 
       "color" : "red",
       "model" : "2011"
    }
}
// Step 1. Get all the object keys.
let evilResponseProps = Object.keys(evilResponse);
// Step 2. Create an empty array.
let goodResponse = [];
// Step 3. Iterate throw all keys.
for (prop of evilResponseProps) { 
    goodResponse.push(evilResponseProps[prop]);
}

Вот ссылка на исходное сообщение. https://medium.com/@papaponmx/looping-over-object-properties-with-ngfor-in-angular-869cd7b2ddcc