我必须重写 Underscore 库中的“调用”方法(一个更简单的版本)来进行赋值,该方法接受方法名称作为参数。到目前为止,我发现应该删除 () 以便将方法作为参数传递而不调用它。
所以我一直在尝试一些事情,但所有这些都会产生不同的结果和错误,如果有人能帮助我理解发生了什么,我将不胜感激。 我并不是在寻找整个作业的答案,而是暗示为什么我会得到这些结果,或者我弄错了哪些语法甚至概念。感谢这些提示,我想自己找到解决方案。
(我已经看过了this,但是1.观察调试器中的'methodName'变量显示'f parseInt()','f join()'(所以......不是字符串),以及2.我的代码似乎可以工作 - 至少部分 - 不使用字符串,所以到目前为止我已经将此选项放在一边。)
好吧……首先,(也是一个更简单的版本)“each”方法,我之前必须重写该方法作为同一作业的一部分,并且我正在尝试重用该方法来实现“invoke”。它通过了我的编码学校提供的所有测试来检查。
_.each = function (collection, iteratee, context) {
let keys = Object.keys(collection);
if (Array.isArray(collection)) {
for (let i=0; i<keys.length; i++) {
iteratee.call(context, collection[keys[i]], i, collection);
}
}
else {
for (let i=0; i<keys.length; i++) {
iteratee.call(context, collection[keys[i]], keys[i], collection);
}
}
return collection;
};
现在这里是“调用”的说明......
// _.invoke(collection, methodName, *arguments)
// Returns an array with the results of calling the method indicated by methodName on each value in the collection.
// Any extra arguments passed to invoke will be forwarded on to the method invocation.
…以及我的三次尝试以及开发工具控制台中的结果。第一个似乎可以与 parseInt 配合使用,但不能与 join 配合使用:
function invoke1 (collection, methodName) {
let resArray = [];
_.each(collection, el => resArray.push(methodName(el)));
return resArray;
}
console.log(invoke1(['1','2','3'], parseInt)); // [123]
console.log(invoke1([['a','b','c'], ['d','e','f']], Array.prototype.join)); // Uncaught TypeError: Cannot convert undefined or null to object - expected ['a,b,c', 'd,e,f']
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.6/underscore-min.js"></script>
第二个则相反:
function invoke2 (collection, methodName) {
let resArray = [];
_.each(collection, el => resArray.push(methodName.apply(el)));
return resArray;
}
console.log(invoke2(['1','2','3'], parseInt)); // [NaN, NaN, NaN] - expected [123]
console.log(invoke2([['a','b','c'], ['d','e','f']], Array.prototype.join)); // ['a,b,c', 'd,e,f']
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.6/underscore-min.js"></script>
在第三个中,我尝试实现参数转发,并删除 join 的默认分隔逗号。
function invoke3 (collection, methodName, ...arg) {
let resArray = [];
_.each(collection, el => resArray.push(methodName.apply(el, ...arg)));
return resArray;
}
console.log(invoke3(['1','2','3'], parseInt)); // [NaN, NaN, NaN] - expected [123]
console.log(invoke3([['a','b','c'], ['d','e','f']], Array.prototype.join, '')); // Uncaught TypeError: CreateListFromArrayLike called on non-object - expected ['abc', 'def']
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.6/underscore-min.js"></script>
parseInt
、structuredClone
需要 this
作为全局上下文。您可以检查该方法是否属于globalThis
并进行相应的调用。在其他情况下,可能需要不同的上下文,因此可能应该将其作为参数提供。Function::apply()
期望第二个参数为参数数组,因此使用 arg
而不是 ...arg
const invoke3 = (collection, method, ...arg) => collection.map(el => globalThis[method.name] === method ? method(el, ...arg) : method.apply(el, arg));
console.log(invoke3(['1','2','3'], parseInt));
console.log(invoke3([['a','b','c'], ['d','e','f']], Array.prototype.join, ''));
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.6/underscore-min.js"></script>