关于高阶函数回调中‘this’的问题

Question about ‘this’ inside higher-order-function's callback

我有一个关于 JavaScript 高阶函数回调中的“this”的问题。

我一直在探索以下代码 - 目标是将接受回调的函数转换为返回承诺的函数。 资料来源:https://javascript.info/promisify

接受回调的函数:

function loadScript(src, callback) {
  let script = document.createElement('script');
  script.src = src;

  script.onload = () => callback(null, script);
  script.onerror = () => callback(new Error(`Script load error for ${src}`));

  document.head.append(script);
}

现在,作者使用了一个高阶函数,它将接受上述函数作为回调并进行 promisification:

function promisify(f) {
  return function (...args) { 
    return new Promise((resolve, reject) => {
      function callback(err, result) { 
        if (err) {
          return reject(err);
        } else {
          resolve(result);
        }
      }

      args.push(callback); 

      f.call(this, ...args); 
    });
  };
};

// usage:

let loadScriptPromise = promisify(loadScript);
loadScriptPromise('path/script.js').then(...);

我不明白的地方是:

为什么要这样调用f函数: f.call(这​​个, ...args); ?

在这种情况下,“this”是什么? 为什么我们不能这样称呼它:f(...args); ?

我知道为了追踪回调的“this”指向什么,您需要检查包含它的高阶函数... 但我不明白为什么在这种情况下我们必须明确说明回调的“this”?

感谢您的帮助!

Why do we call the f function in this way: f.call(this, ...args); ?

What will ‘this’ be in this case? Why can't we just call it like this: f(...args); ?

让我先回答 在这种情况下“这”是什么? 第一部分:

我们不知道(总的来说),这就是为什么使用 .call,但我会说的。

promisify 应该“无缝地”包装现有函数。这意味着调用 fpromisify(f) 应该 return 相同的结果。

this 的值取决于如何 函数被调用promisify不知道新的包装函数将如何被调用,也不知道包装函数是否使用this。因此,它需要假设 this 将很重要,并且必须以正确设置 this 的方式调用包装函数。
调用函数并显式设置 this 值的唯一方法是通过 .call.apply。如果函数被调用为 f(...args) 那么 f 里面的 this 要么是全局对象要么是 undefined.

这是一个更简单的包装函数来演示这个问题:

function wrapWithThis(f) {
  return function(...args) {
    f.call(this, ...args);
  }
}

function wrapWithoutThis(f) {
  return function(...args) {
    f(...args);
  }
}

function wrapMe() {
  console.log(this.foo);
}

const obj = {
  foo: 42,
  withThis: wrapWithThis(wrapMe),
  withoutThis: wrapWithoutThis(wrapMe),
};

obj.withThis();
obj.withoutThis();


说了这么多,具体到你的例子,鉴于 loadScript 不使用 this,如果 f.call(this, ...) 或 [=32= 不会有什么不同]被使用了。