2015-12-30 15 views
5

C'è un modo per passare argomenti a lodash _.result, per il caso, quando il secondo attributo è il nome del metodo? Oppure esiste un metodo alternativo (preferal lodash) per farlo?Passare argumets a lodash _.result

esempio di utilizzo potrebbe essere simile a questo:

var object = { 
    'cheese': 'crumpets', 
    'stuff': function(arg1) { 
    return arg1 ? 'nonsense' : 'balderdash'; 
    } 
}; 

_.result(object, 'cheese'); 
// => 'crumpets' 

_.result(object, 'stuff', true); 
// => 'nonsense' 

_.result(object, 'stuff'); 
// => 'balderdash' 

Grazie.

+1

I documenti non sembrano mostrare alcun modo per realizzare questo https://lodash.com/docs#result (se ho capito bene) quindi la mia ipotesi è che questo non è supportato. Potresti chiedere qui https://github.com/lodash/lodash/issues per essere sicuro, o addirittura richiederlo come funzionalità aggiuntiva. – Xotic750

risposta

1

Ho guardato il codice sorgente della funzione lodash _.result e non c'è supporto per questo. Puoi implementare la tua funzione per questo ed estendere lodash con esso usando _. mixin.

function myResult(object, path, defaultValue) { 
    result = object == null ? undefined : object[path]; 
    if (result === undefined) { 
     result = defaultValue; 
    } 
    return _.isFunction(result) 
     ? result.apply(object, Array.prototype.slice.call(arguments, 2)) 
     : result; 
} 

// add our function to lodash 
_.mixin({ myResult: myResult}) 


_.myResult(object, 'cheese'); 
// "crumpets" 

_.myResult(object, 'stuff', true); 
// "nonsense" 

_.myResult(object, 'stuff'); 
// "balderdash" 
+0

Grazie per la soluzione piuttosto semplice! –

+0

Basta essere consapevoli che questa soluzione non offre tutte le funzionalità di '_.result' in diversi modi. – Xotic750

1

È possibile creare il proprio mixin. Ecco un esempio utilizzando la prossima uscita lodash 4.0.0

var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/; 
 
var reIsPlainProp = /^\w*$/; 
 
var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g; 
 
var reEscapeChar = /\\(\\)?/g; 
 

 
function isKey(value, object) { 
 
    if (typeof value == 'number') { 
 
    return true; 
 
    } 
 
    return !_.isArray(value) && 
 
    (reIsPlainProp.test(value) || !reIsDeepProp.test(value) || 
 
     (object != null && value in Object(object))); 
 
} 
 

 
function stringToPath(string) { 
 
    var result = []; 
 
    _.toString(string).replace(rePropName, function(match, number, quote, string) { 
 
    result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); 
 
    }); 
 
    return result; 
 
} 
 

 
function baseToPath(value) { 
 
    return _.isArray(value) ? value : stringToPath(value); 
 
} 
 

 
function parent(object, path) { 
 
    return path.length == 1 ? object : _.get(object, _.slice(path, 0, -1)); 
 
} 
 

 
function customResult(object, path, args, defaultValue) { 
 
    if (!isKey(path, object)) { 
 
    path = baseToPath(path); 
 
    var result = get(object, path); 
 
    object = parent(object, path); 
 
    } else { 
 
    result = object == null ? undefined : object[path]; 
 
    } 
 
    if (result === undefined) { 
 
    result = defaultValue; 
 
    } 
 
    return _.isFunction(result) ? result.apply(object, _.isArrayLike(args) ? args : []) : result; 
 
} 
 

 
_.mixin({ 
 
    'customResult': customResult 
 
}); 
 

 
var object = { 
 
    'cheese': 'crumpets', 
 
    'stuff': function(arg1) { 
 
    return arg1 ? 'nonsense' : 'balderdash'; 
 
    } 
 
}; 
 

 
var out = document.getElementById('out'); 
 
out.textContent = _.customResult(object, 'cheese') + '\n'; 
 
// => 'crumpets' 
 

 
out.textContent += _.customResult(object, 'stuff', [true]) + '\n'; 
 
// => 'nonsense' 
 

 
out.textContent += _.customResult(object, 'stuff') + '\n'; 
 
// => 'balderdash'
<script src="https://rawgit.com/lodash/lodash/master/lodash.js"></script> 
 
<pre id="out"></pre>

ho usato le funzioni esatte dalle funzionamento interno di lodash ma si può essere in grado di farlo con appena esposto metodi. Se avrò qualche minuto di ricambio, darò un'occhiata se è possibile.

Il problema con l'utilizzo dei soli metodi esposti è che non vedo alcun modo per eseguire la funzione con il contesto corretto.

Questo metodo è come _.get tranne che se il valore risolto è una funzione viene invocato con l'questo legame del suo oggetto genitore e il suo risultato viene restituito.

+0

L'idea è chiara, grazie. Quindi sembra che risolva un compito più generale, come "risultato" profondo? –

+0

Nel metodo 'customResult' dovrebbe essere il metodo' _.get' e in seguito '_.slice' invece di' _slice', suppongo. –

+1

Sì, questa soluzione funziona proprio come il '_.result' originale, aggiunge semplicemente l'argomento' args' al metodo. – Xotic750

1

Ecco un'altra implementazione mixin:

function myResult(obj, path, defaultValue) { 

    // Find any arguments beyond what's normally 
    // passed to result(). 
    var args = _.drop(arguments, 3); 

    // We need to know upfront whether or not this 
    // is a function we're dealing with. 
    var isFunc = _.isFunction(_.get(obj, path)); 

    // If this is a function, and there's arguments 
    // to apply, then use spread() and bindKey() to 
    // return the result of calling the method with arguments. 
    // Otherwise, it's just a plain call to result(). 
    if (isFunc && args.length) { 
     return _.spread(_.bindKey(obj, path))(args); 
    } else { 
     return _.result(obj, path, defaultValue); 
    } 
} 

_.mixin({ myResult: myResult }); 

L'idea è che abbiamo solo bisogno di gestire il caso in cui aggiunto path è una funzione sono stati passati e argomenti aggiuntivi. In caso contrario, torniamo all'implementazione di base result().

_.myResult(object, 'test'); 
// → undefined 

_.myResult(object, 'test', 15); 
// → 15 

_.myResult(object, 'cheese', 'wine'); 
// → "crumpets" 

_.myResult(object, 'stuff'); 
// → "balderdash" 

_.myResult(object, 'stuff', null, true); 
// → "nonsense"