Lodash使用后卫链

时间:2015-08-14 19:56:52

标签: javascript lodash

我尝试使用rearg使用和不使用链接,并且在使用链接时我只会收到错误。我已经阅读了文档,它看起来像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();

2 个答案:

答案 0 :(得分:2)

我知道这个问题已经过时了,但这是关于Lodash链接的罕见SO问题之一仍然没有答案,试图回答它让我可以深入挖掘文档并理解这个库... 这是一个尝试运行JS代码的好机会" Stack Overflow的功能......

我终于明白它不能像你一样工作。

首先,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);
&#13;
<div id="pls-results"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

这个答案扩展到PhiLho's excellent answer。希望这将有助于未来的读者更多地了解问题和解决方案。 在以下代码段中,您可以看到与PhiLho的代码段相同的结果以及其他2个测试:

  1. 链接_.difference而不是_.reverseDiff :当对象在keyList中找不到某些键时返回结果(而不是keyList中找不到键的键)在对象中。)。
  2. 直截了当的替代方法( _.difference(myList, _.keys(myJSON)) ):以较少的代码返回预期的输出(此问题的意图可能与此解决方案无关,但通过显示此替代方案,您可能更容易理解问题)。
  3. &#13;
    &#13;
    // 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)); });
    &#13;
    <div id="pls-results"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
    &#13;
    &#13;
    &#13;