javascript - 有没有安全的方法调用 `call` 来调用 JavaScript 中的函数?

标签 javascript function call

我想调用一个带有自定义 thisArg 的函数。

这看起来很简单,我只需要调用call:

func.call(thisArg, arg1, arg2, arg3);

但是等等! func.call 可能不是 Function.prototype.call

所以我想到了用

Function.prototype.call.call(func, thisArg, arg1, arg2, arg3);

但是等等! Function.prototype.call.call 可能不是 Function.prototype.call

因此,假设 Function.prototype.call 是原生的,但考虑到可能已将任意非内部属性添加到其中,ECMAScript 是否提供了一种安全的方法来执行以下操作?

func.[[Call]](thisArg, argumentsList)

最佳答案

这就是鸭子类型的力量(和风险):if typeof func.call === 'function',那么您应该将其视为一个普通的可调用函数。 func 的提供者需要确保他们的 call 属性与公共(public)签名相匹配。我实际上在几个地方使用了它,因为 JS 没有提供重载 () 运算符和提供经典仿函数的方法。

如果你真的需要避免使用 func.call,我会使用 func() 并要求 func 接受 thisArg 作为第一个参数。由于 func() 没有委托(delegate)给 call(即,f(g, h) 没有 desugar 给 f。 call(t, g, h)) 并且您可以在括号的左侧使用变量,它将为您提供可预测的结果。

您还可以在加载库时缓存对 Function.prototype.call 的引用,以防它稍后被替换,并在以后使用它来调用函数。这是 lodash/underscore 用来获取 native 数组方法的模式,但不提供任何实际保证您将获得原始 native 调用方法。它可以变得非常接近并且不是非常丑陋:

const call = Function.prototype.call;

export default function invokeFunctor(fn, thisArg, ...args) {
  return call.call(fn, thisArg, ...args);
}

// Later...
function func(a, b) {
  console.log(this, a, b);
}

invokeFunctor(func, {}, 1, 2);

这是任何具有多态性的语言中的一个基本问题。在某些时候,您必须相信对象或库会按照其约定行事。与任何其他情况一样,信任但验证:

if (typeof duck.call === 'function') {
  func.call(thisArg, ...args);
}

通过类型检查,您还可以进行一些错误处理:

try {
  func.call(thisArg, ...args);
} catch (e) {
  if (e instanceof TypeError) { 
    // probably not actually a function
  } else {
    throw e;
  }
}

如果您可以牺牲 thisArg(或强制它成为一个实参),那么您可以进行类型检查并使用括号调用:

if (func instanceof Function) {
  func(...args);
}

关于javascript - 有没有安全的方法调用 `call` 来调用 JavaScript 中的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31076798/

相关文章:

javascript - js : attempting to hook fine-uploader into a flask application

javascript - 遍历对象,其中值是对象数组,并从对象数组的每个对象返回一个值

javascript - 对象在javascript中使用自己的方法

java - 如何使用 'ADD'按钮重复添加JPanel?如何在ActionListener()中调用JPanel?

java - 两个构造函数调用之间的区别

javascript - Node.js 类型错误 : callBack is not a function

javascript - 为什么我的 Backbone Collection 重置事件没有触发?

javascript - Base64加密后运行JavaScript代码

javascript - 如何将数组链接到 html 中的 javascript 函数?

function - 如何使用 GetProcAddress 函数调用 MessageBox?