/**
* @file obj.js
* @module obj
*/
/**
* @callback obj:EachCallback
*
* @param {Mixed} value
* La clé actuelle de l'objet sur lequel l'itération est effectuée.
*
* @param {string} key
* La valeur-clé actuelle de l'objet qui est en cours d'itération
*/
/**
* @callback obj:ReduceCallback
*
* @param {Mixed} accum
* La valeur qui s'accumule au cours de la boucle de réduction.
*
* @param {Mixed} value
* La clé actuelle de l'objet sur lequel l'itération est effectuée.
*
* @param {string} key
* La valeur-clé actuelle de l'objet qui est en cours d'itération
*
* @return {Mixed}
* La nouvelle valeur accumulée.
*/
const toString = Object.prototype.toString ;
/**
* Obtenir les clés d'un objet
*
* @param {Objet}
* L'objet à partir duquel les clés sont obtenues
*
* @return {string[]}
* Un tableau des clés de l'objet. Renvoie un tableau vide si le
* transmis n'était pas valide ou n'avait pas de clés.
*
* @private
*/
const keys = function(object) {
return isObject(object) ? Object.keys(object) : [] ;
};
/**
* Itération de type tableau pour les objets.
*
* @param {Object} object
* L'objet sur lequel itérer
*
* @param {obj:EachCallback} fn
* La fonction de rappel qui est appelée pour chaque clé de l'objet.
*/
export function each(object, fn) {
keys(object).forEach(key => fn(object[key], key)) ;
}
/**
* Réduction de type tableau pour les objets.
*
* @param {Object} object
* L'objet que vous souhaitez réduire.
*
* @param {Fonction} fn
* Une fonction de rappel qui est appelée pour chaque clé de l'objet. Il
* reçoit la valeur accumulée et la valeur par itération et la clé
* comme arguments.
*
* @param {Mixed} [initial = 0]
* Valeur de départ
*
* @return {Mixed}
* La valeur finale accumulée.
*/
export function reduce(object, fn, initial = 0) {
return keys(object).reduce((accum, key) => fn(accum, object[key], key), initial) ;
}
/**
* Fusion/extension superficielle d'objets dans le style Object.assign.
*
* @param {Objet} target
* @param {Objet} ...sources
* @return {Object}
*/
export function assign(target, ...sources) {
if (Object.assign) {
return Object.assign(target, ...sources) ;
}
sources.forEach(source => {
if (!source) {
retour ;
}
each(source, (value, key) => {
cible[clé] = valeur ;
}) ;
}) ;
retourner la cible ;
}
/**
* Indique si une valeur est un objet de n'importe quel type, y compris les nœuds du DOM,
* tableaux, expressions régulières, etc. Mais pas de fonctions.
*
* Cela permet d'éviter le piège de l'utilisation de `typeof` sur une valeur `null`
* aboutit à ``objet''.
*
* @param {Objet} valeur
* @return {boolean}
*/
export function isObject(value) {
return !!value && typeof value === 'object' ;
}
/**
* Indique si un objet semble être un objet "ordinaire", c'est-à-dire un objet de type
* instance directe de `Object`.
*
* @param {Objet} valeur
* @return {boolean}
*/
export function isPlain(value) {
return isObject(valeur) &&
toString.call(value) === '[object Object] &&
value.constructor === Object ;
}