在JS中调用函数时如何使用逻辑NOT(!)运算符?

giw*_*ook 2 javascript operators logical-operators underscore.js

我正在从下划线库重新创建函数,但在尝试实现该_.reject()函数时遇到了障碍.对于这个问题的目的,我会包括我的三个功能编写的代码:_.each(),_.filter(),和_.reject().

_.each = function(collection, iterator) {
  if (Array.isArray(collection)) {
    for (var i = 0; i < collection.length; i++) {
      iterator(collection[i], i, collection);
    }
  } else {
    for (var i in collection) {
      iterator(collection[i], i, collection);
    }
  }
};

_.filter = function(collection, test) {
    var results = [];

    _.each(collection, function(i) {
      if (test(i)) {
        results.push(i);
      }
    })

    return results;
};
Run Code Online (Sandbox Code Playgroud)

这里是我遇到问题的函数的代码,_.reject()方法,以及isEven()我作为test参数传递的函数.

_.reject = function(collection, test) {
    return _.filter(collection, !test);
}; 

var isEven = function(x) {
    if (x % 2 === 0) return true;
    return false;
};
Run Code Online (Sandbox Code Playgroud)

根据MDN的表达式和运算符页面,逻辑NOT(!)运算符Returns false if its single operand can be converted to true; otherwise, returns true.

但是,当我运行以下代码时,_.reject([1,2,3], isEven)我得到一个错误说test is not a function.为什么我!在调用函数时无法使用运算符(例如_.filter([1,2,3], !isEven))?

Fel*_*ing 7

为什么我!在调用函数时无法使用运算符(例如,_.filter([1,2,3], !isEven))

请注意,您实际上没有调用isEven,只是引用它.正如您所说,! "如果单个操作数可以转换为true,则返回false;否则返回true."

isEven是对函数的引用,即对象.对象转换为true,因此!test导致false:

_.filter([1,2,3], false))
Run Code Online (Sandbox Code Playgroud)

现在您传递的是布尔而不是函数_.filter,因此错误消息"test is not a function".

相反,您必须传递一个否定测试函数结果的函数:

_.filter([1,2,3], function() {
    return !test.apply(this, arguments);
});
Run Code Online (Sandbox Code Playgroud)


T.J*_*der 7

当你引用一个函数而不是调用它时,你指的是函数的对象引用:

function foo() {
    alert("Hi there");
}

var f = foo; // <== Getting the function's reference, not calling it
f();         // <== Now we call it
Run Code Online (Sandbox Code Playgroud)

所以!isEven会否定函数引用.由于isEven是非null参考,它是真实的; 所以!isEvenfalse.不是你想要的.:-)

reject可以使用调用test并反转其返回值的函数编写:

_.reject = function(collection, test) {
  return _.filter(collection, function(e) { return !test(e); });
};
Run Code Online (Sandbox Code Playgroud)

或者如果你想使用函数式编程方法,你可以编写一个函数,当被调用时,它将返回一个否定返回值的函数:

function not(f) {
    return function() {
        return !f.apply(this, arguments);
    };
}
Run Code Online (Sandbox Code Playgroud)

然后你想要反转一个回调的含义,你只需使用invert:

_.reject = function(collection, test) {
  return _.filter(collection, not(test));
};
Run Code Online (Sandbox Code Playgroud)