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))?
为什么我
!在调用函数时无法使用运算符(例如,_.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)
当你引用一个函数而不是调用它时,你指的是函数的对象引用:
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参考,它是真实的; 所以!isEven是false.不是你想要的.:-)
您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)