通过名称传递/调用 JS 方法

问题描述 投票:0回答:1

我必须重写 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>

javascript function methods parameters arguments
1个回答
0
投票
  1. 许多全局方法,如
    parseInt
    structuredClone
    需要
    this
    作为全局上下文。您可以检查该方法是否属于
    globalThis
    并进行相应的调用。在其他情况下,可能需要不同的上下文,因此可能应该将其作为参数提供。
  2. 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>

© www.soinside.com 2019 - 2024. All rights reserved.