2015-08-14 4 views
2

Я пробовал использовать rearg с цепью и без нее, и я получаю ошибку при использовании цепочки. Я прочитал документы, и мне кажется, что rearg должен хорошо сочетаться с цепочкой, поскольку он возвращает метод скрепляемой оберткой. Тем не менее, я получаю следующее сообщение об ошибке:Lodash using rearg в цепи

Error: _.chain(...).keys(...).myFunc is not a function 

с этим кодом:

var myList = ['a','b','c','d'] 
var myJSON = { 
    'a':1, 
    'b':2 
}; 

var myFunc = _.rearg(_.difference, [1, 0]); //switching order of arguments 

var hasAllKeys = _.chain(myJSON) 
        .keys() 
        .myFunc(myList) 
        .value(); 

Конечно, этот код работает отлично (хотя выход не то, что мне нужно):

var wrong = _.chain(myJSON) 
      .keys() 
      .difference(myList) 
      .values(); 
+0

MyFunc (MyList) возвращает []. Это то, чего вы ожидаете? –

+0

Будет ли другое решение цепочки, не использующее rearg, быть хорошим для вас? –

ответ

2

Я знаю, что вопрос старый, но это один из редких вопросов SO о цепочке в Lodash, остающемся без ответа, и попытка ответить на него позволяет мне глубже копать в документации и понимать эту библиотеку ... И это хорошая возможность попробовать функцию «Run JS code» для переполнения стека ...

Наконец-то я понял, что он не может работать так, как вы.

Во-первых, это rearg действительно цельный? Ответ: да. Я пытался с этим кодом:

var last = _(twoParams).ary(1).rearg([1, 0]).value(); 

и в самом деле, когда я называю last с двумя параметров, она вызывает twoParams только с последним.

Конечно, rearg может быть только закодирован с функциями, предоставляющими функцию как выход, и ожидая, что функция будет введена, т. Е. только в цепочке функций обработки функций.

Теперь ваш код не работает, потому что если rearg является цепным, его выход не является! Его выход представляет собой простую старую функцию JavaScript, и они не связаны друг с другом. Хорошей новостью является то, что Lodash, в своей великой мудрости, обеспечивает способ сделать функцию цепочки. Вы должны использовать mixin, который по умолчанию добавляет предоставленную функцию к Lodash и делает ее цельной. См., Например, Create chain in lodash with custom functions, в котором объясняется, как это сделать. В отличие от этих примеров, я буду следовать рекомендациям документации Lodash и использовать runInContext, чтобы избежать загрязнения Lodash новой функцией, которая должна оставаться локальной.

Вот мои эксперименты. Я взял на себя смелость переименовать некоторые идентификаторы, как я ненавижу имена myXxx и предпочитают более описательные имена ...

// Generic code to display resuts 
 

 
var results = document.getElementById('pls-results'); 
 
function showHTML(html) 
 
{ 
 
    results.insertAdjacentHTML('beforeend', html); 
 
} 
 
function show(text) 
 
{ 
 
    showHTML("<p>" + text + "<p>"); 
 
} 
 
function showObject(obj) 
 
{ 
 
    show("<p>" + JSON.stringify(obj) + "<p>"); 
 
} 
 

 
// The real code 
 

 
var keyList = [ 'a', 'b', 'c', 'd' ]; 
 
var incompleteJson = { "a": 1, "b": 2 }; 
 
var fullJson = { "a": 1, "b": 2, "c": true, "d": "yes" }; 
 

 
// A simple way to do what is implied by the variable name 
 
showHTML("<h3>Has All Keys</h3>"); 
 

 
show("Incomplete Json"); 
 

 
var diff = _.difference(keyList, _.keys(incompleteJson)); 
 
var hasAllKeys = diff.length === 0; 
 

 
show(hasAllKeys); 
 

 
show("Full Json"); 
 

 
diff = _.difference(keyList, _.keys(fullJson)); 
 
hasAllKeys = diff.length === 0; 
 

 
show(hasAllKeys); 
 

 
// What you try to do 
 
showHTML("<h3>Consume Expected Keys</h3>"); 
 

 
var localLodash = _.runInContext(); 
 
localLodash.mixin(
 
    { 
 
     'reverseDiff': _.rearg(_.difference, [1, 0]) // switching order of arguments 
 
    } 
 
); 
 

 
show("Incomplete Json"); 
 

 
var expectedKeys = localLodash.chain(incompleteJson) 
 
    .keys() 
 
    .reverseDiff(keyList) 
 
    .value(); 
 

 
showObject(expectedKeys); 
 

 
show("Full Json"); 
 

 
expectedKeys = localLodash.chain(fullJson) 
 
    .keys() 
 
    .reverseDiff(keyList) 
 
    .value(); 
 

 
showObject(expectedKeys);
<div id="pls-results"></div> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>

1

Этот ответ расширяет PhiLho's excellent answer. Надеемся, это поможет будущим читателям лучше понять проблему и решения. В следующем фрагменте кода, вы можете увидеть те же результаты, как в фрагменте кода PhiLho в, а также 2 других тестов:

  1. СЦЕПЛЕНИЕ _.difference вместо _.reverseDiff: Что возвращает результаты, когда объект имеет некоторые ключи не найдены в keyList (вместо того, чтобы быть ключевым списком, который имеет ключи, которые не найдены в объекте).
  2. Прямая альтернатива (): которая возвращает ожидаемый результат с меньшим количеством кода (цель этого вопроса, вероятно, не в этом решении, но, показывая эту альтернативу, вы, вероятно, можете легче понять проблему).

// Generic code to display resuts 
 
var results = document.getElementById('pls-results'); 
 
function showHTML(html) { 
 
    results.insertAdjacentHTML('beforeend', html); 
 
} 
 

 
// Set up test data 
 
var keyList = [ 'a', 'b', 'c', 'd' ]; 
 
var incompleteJson = { "a": 1, "b": 2 }; 
 
var fullJson = { "a": 1, "b": 2, "c": true, "d": "yes" }; 
 
var extraPropertyJson = { "a": 1, "b": 2, "c": true, "d": "yes", 'z': 26 }; 
 

 
// Set up test helper methods 
 
var renderLine = function(label, obj) { 
 
    return "<tr><td>" + label + "</td><td>" + JSON.stringify(obj) + "</td></tr>"; 
 
}; 
 
var test = function(funcName, funcToTest) { 
 
    var html = "<h3>" + funcName + "</h3><table>"; 
 
    html += renderLine("Incomplete Json", funcToTest(incompleteJson)); 
 
    html += renderLine("Full Json", funcToTest(fullJson)); 
 
    html += renderLine("Extra Property Json", funcToTest(extraPropertyJson)); 
 
    html += "</table>"; 
 
    showHTML(html); 
 
}; 
 

 
// The real code 
 
var local_ = _.runInContext(); 
 
local_.mixin({ 
 
    'reverseDiff': _.rearg(_.difference, [1, 0]) // switching order of arguments 
 
}); 
 

 
// Tests execution 
 
test("_.difference",      function(json) { return  _.chain(json).keys(). difference(keyList).value(); }); 
 
test("local_.reverseDiff",     function(json) { return local_.chain(json).keys().reverseDiff(keyList).value(); }); 
 
test("_.difference(keyList, _.keys(json))", function(json) { return _.difference(keyList, _.keys(json)); });
<div id="pls-results"></div> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>