2012-06-13 14 views
6

tengo dos objetos de javascript:valores por defecto Sacar de un objeto

var a = { 
    x: 1, 
    y: { 
     faz: 'hello', 
     baz: '' 
    }, 
    z: [1, 2] 
}; 


var defaults = { 
    x: 2, 
    y: { 
     faz: '', 
     baz: '' 
    }, 
    z: [1, 2] 
}; 

quiero sólo para mantener los campos de a que son diferente del defecto:

a = remove_defaults(a, defaults); // <---- i need this fnc 
{ 
    x: 1, 
    y: { 
     faz: 'hello' 
    } 
} 

El objetivo es para eliminar valores predeterminados de un objeto que sirve como estado (a través de URL). El estado puede tener campos anidados, por lo que una comparación superficial no es suficiente. Los valores de las hojas son todos primitivos (número, cadena, bool).

(esto es un poco como lo contrario de underscore.js 's _.defaults() método)

¿Cuál es la mejor manera de lograr esto?


La solución se puede utilizar underscore.js si eso ayuda, pero sin jquery.

+1

itere recursivamente sobre las propiedades y compare sus valores. No hay un método incorporado. –

Respuesta

3

Prueba esto:

function removeDuplicates(a, defaults, result) { 
    for (var i in a) { 
    if (i in defaults) { 
     if (typeof a[i] == "object" 
      && typeof defaults[i] == "object" 
      && Object.prototype.toString.call(defaults[i]) !== '[object Array]') { 
     result[i] = removeDuplicates(a[i], defaults[i], {}); 
     } else if (a[i] !== defaults[i]) { 
     result[i] = a[i]; 
     } 
    } else { 
     result[i] = a[i]; 
    } 
    } 

    return result; 
} 


var result = removeDuplicates(a, defaults, {}); 
+1

¡Salud! Pero, ¿para qué sirve la parte 'a [i] && '? Eso ignorará todo false, como 'false',' 0', '''', 'undefined', que parece un error? – user124114

+1

tienes razón, he reparado el código. – ioseb

+0

Oh, me acabo de dar cuenta de que hay un error masivo allí - ¡todos los campos copiados van al alcance global de 'resultado', en lugar de a sus respectivos subcampos! – user124114

1
function remove_defaults(obj, defaults) { 
    for (var i in obj) { 
    if (typeof obj[i] == 'object') { 
     obj[i] = remove_defaults(obj[i], defaults[i]); 
     continue; 
    } 
    if (defaults[i] !== undefined && obj[i] == defaults[i]) { 
     delete obj[i]; 
    } 
    } 
    return obj; 
} 

violín: http://jsfiddle.net/ybVGq/

+0

Esto deja la matriz 'z' en el resultado. Creo que la solución de @ioseb es mejor, porque eso también elimina los objetos anidados una vez que están completamente vacíos (= todos los valores internos eran iguales a los valores predeterminados). – user124114

+0

Sí, me di cuenta de eso. Eso es porque estaba usando 'delete' en lugar de crear una nueva matriz. – jeremyharris

0

Mi propia visión:

function no_defaults(obj, defaults) { 
    if ((obj instanceof Array) && (defaults instanceof Array)) { 
     var result = _.difference(obj, defaults); 
     return _.isEmpty(result) ? undefined : result; 
    } 
    if ((obj instanceof Array) || (defaults instanceof Array)) 
     return _.clone(obj); 
    if (typeof obj == "object" && typeof defaults == "object") { 
     var result = {}; 
     for (var prop in obj) { 
      var res = prop in defaults ? no_defaults(obj[prop], defaults[prop]) : _.clone(obj[prop]); 
      if (res !== undefined) 
       result[prop] = res; 
     } 
     return _.isEmpty(result) ? undefined : result; 
    } 
    return _.isEqual(obj, defaults) ? undefined : _.clone(obj); 
} 

recordar este-procesos profundos objetos, pero no arrays. Las matrices solo se procesan para la diferencia superficial de sus elementos directos; si los elementos necesitan no_default ing, esta función no funcionará. Pero esto está bien para mi caso de uso previsto.

Cuestiones relacionadas