2013-01-11 11 views
10

Załóżmy, że mam następny obiekt javascript. Teraz chcę go sklonować, ale bez niektórych pól. Na przykład chcę, sklonowany obiekt bez pola "lastName" i "cars.age"
WejścieGłęboki klon bez niektórych pól

{ 
    "firstName":"Fred", 
    "lastName":"McDonald", 
     "cars":[ 
      { 
       "type":"mersedes", 
       "age":5 
      }, 
      { 
       "model":"bmw", 
       "age":10 
      } 
     ] 
} 

Wyjście (sklonowanego)

{ 
    "firstName":"Fred", 
    "cars":[ 
     { 
      "model":"mersedes" 
     }, 
     { 
      "model":"bmw" 
     } 
    ] 
} 

mogę zrobić coś

var human = myJson 
var clone = $.extend(true, {}, human) 
delete clone.lastName 
_.each(clone.cars, function(car)) 
{ 
    delete car.age 
} 

Czy znasz łatwiejsze rozwiązanie?

+1

Nie ma mowy, aby odfiltrować sklonowanych członków użyciem '$ .extend', ale można toczyć własną implementację, że są pomijane pola ... –

+0

Chciałbym utworzyć funkcja, która akceptuje obiekt do sklonowania i tablicę właściwości, które mają zostać usunięte (lub dołączone) do nowego obiektu. W jQuery nie ma wbudowanej metody. –

+0

Underscore.js zawiera funkcję 'pluck', która jest rodzajem odwrotnej wersji tego, co chcesz: Określ, co chcesz dołączyć, a nie to, co chcesz pominąć. Być może to może stanowić punkt wyjścia dla twojej implementacji? – Henrik

Odpowiedz

6

Jeśli nie masz nic przeciwko dodawaniu prototypów do obiektów, jest to proste rozwiązanie. Możesz go trochę zmodyfikować do własnego użytku.

Object.prototype.deepOmit = function(blackList) { 
    if (!_.isArray(blackList)) { 
    throw new Error("deepOmit(): argument must be an Array"); 
    } 

    var copy = _.omit(this, blackList); 
    _.each(blackList, function(arg) { 
    if (_.contains(arg, '.')) { 
     var key = _.first(arg.split('.')); 
     var last = arg.split('.').slice(1); 
     copy[key] = copy[key].deepOmit(last); 
    } 
    }); 
    return copy; 
}; 

Array.prototype.deepOmit = function(blackList) { 
    if (!_.isArray(blackList)) { 
    throw new Error("deepOmit(): argument must be an Array"); 
    } 

    return _.map(this, function(item) { 
    return item.deepOmit(blackList); 
    }); 
}; 

Wtedy, kiedy mamy obiekt jak:

var personThatOwnsCars = { 
    "firstName":"Fred", 
    "lastName":"McDonald", 
     "cars":[ 
      { 
       "type":"mersedes", 
       "age":5 
      }, 
      { 
       "model":"bmw", 
       "age":10 
      } 
     ] 
}; 

można czarować tak.

personThatOwnsCars.deepOmit(["firstName", "cars.age"]); 

A może nawet magia!

[person1, person2].deepOmit(["firstName", "cars.age"]); 
+2

Jeśli używasz już podkreślenia, prawdopodobnie lepiej jest użyć' _.mixin' zamiast prototypów. –

5

Oto samodzielna funkcja w zależności od lodash/podkreślenia, że ​​napisałem, że robi to samo.

Wywołuje wywołanie zwrotne dla każdej pary (value, indexOrKey) w obiekcie lub tablicy, a jeśli true, pominie tę parę w wynikowym obiekcie.

Oddzwonienie jest wywoływane po odwiedzeniu wartości, dzięki czemu można pominąć całe pod-drzewo wartości, które pasują do twojego stanu.

function deepOmit(sourceObj, callback, thisArg) { 
    var destObj, i, shouldOmit, newValue; 

    if (_.isUndefined(sourceObj)) { 
     return undefined; 
    } 

    callback = thisArg ? _.bind(callback, thisArg) : callback; 

    if (_.isPlainObject(sourceObj)) { 
     destObj = {}; 
     _.forOwn(sourceObj, function(value, key) { 
      newValue = deepOmit(value, callback); 
      shouldOmit = callback(newValue, key); 
      if (!shouldOmit) { 
       destObj[key] = newValue; 
      } 
     }); 
    } else if (_.isArray(sourceObj)) { 
     destObj = []; 
     for (i = 0; i <sourceObj.length; i++) { 
      newValue = deepOmit(sourceObj[i], callback); 
      shouldOmit = callback(newValue, i); 
      if (!shouldOmit) { 
       destObj.push(newValue); 
      } 
     } 
    } else { 
     return sourceObj; 
    } 

    return destObj; 
} 

Niektóre próbki

var sourceObj = { 
    a1: [ undefined, {}, { o: undefined } ], 
    a2: [ 1, undefined ], 
    o: { s: 's' } 
}; 

deepOmit(sourceObj, function (value) { 
    return value === undefined; 
}); 
//=> { a1: [ {}, {} ], a2: [ 1 ], o: { s: 's' }} 

//omit empty objects and arrays too 
deepOmit(sourceObj, function (value) { 
    return value === undefined || 
     (_.isPlainObject(value) && !_.keys(value).length) || 
     (_.isArray(value) && !value.length); 
}); 
//=> { a2: [ 1 ], o: { s: 's' }} 

//indexOrKey is the string key or the numeric index if the object is array 
deepOmit([ 0, 1, 2, 3, 4 ], function (value, indexOrKey) { 
    return indexOrKey % 2; 
}); 
//=> [ 0, 2, 4 ] 
Powiązane problemy