Promise.resolve 内部引用混乱

Promise.resolve internal referencing confusion

我正在学习 JS 并在 MDN

中看到了这个片段

var promise1 = Promise.resolve(123);

promise1.then(function(value) {
  console.log(value);
  // expected output: 123
});

如果我修改上面的代码片段并将 console.log 作为 然后 参数传递,我会得到相同的结果。

var promise1 = Promise.resolve(123);

promise1.then(console.log);

我想知道第二个代码如何:

  1. 123 被内部引用,因为我没有将它作为 then 的参数传递。

  2. 当我通过 console.log 而不调用它“ console.log(value) ”时,它是如何执行的以及另外的日志记录123.

Promise 有自己的状态,包括:

  • 它们是待定还是已解决已完成,或拒绝)
  • 如果完成,他们的完成值
  • 如果被拒绝,他们的拒绝原因

Promise.resolve 是一个效用函数,它创建一个 解析为 你传递给它的承诺。由于您向它传递了一个简单的值,它会得到该值的满足,该值成为其状态的一部分。 (与简单值相反,您可以将其解析为 thenable [松散地,一个承诺],在这种情况下,当另一个 thenable 实现或拒绝时,它会被实现或拒绝。)

稍后,当您使用 then 附加履行处理程序时,它会使用该履行值调用您的处理程序(即使它已经履行)。对于真正的 Promise,该调用始终是异步的(即使在您调用 then 时承诺已经实现)。 (对于 thenable,它可能是也可能不是异步的。)

这些条款在 Promises/A+ spec. See also Domenic Denicola's States and Fates 页面中列出。

回到你的问题:

  1. The value 123 is being internally referenced as i have not passed it as a parameter of then.

是的,它作为状态信息(履行价值)存储在承诺中。

  1. When i pass console.log without calling it " console.log(value) ", how is it executing and in addition logging 123.

console.log 是一个函数。函数是 JavaScript 中的 first-class 对象,这意味着您可以传递它们。碰巧 console.log 不关心它的 this 值是什么,所以你可以只传递函数而无需绑定 this 值。

从根本上说,then 正在做同样的事情 example 在这里:

function example(handler) {
    // `setTimeout` is NOT really used by the promise implementation;
    // promises queue a "promise job" instead
    setTimeout(() => {
        handler(123);
    }, 0);
}

example(console.log);


[关于我在上面 setTimeout 上的注释:setTimeout 不是 他们真正使用的东西。相反,他们排队 "promise job"(又名 "microtask")。所有 JavaScript 代码 运行 都是作业队列中作业的一部分。当脚本作业完成时(在从脚本作业队列中取出下一个脚本作业之前,即使该脚本作业等待的时间比承诺的工作还要长。]

  1. 语句 console.log 将对函数 log 的引用放在堆栈上的 console 对象上。
  2. Promise.prototype.then 的签名表明它需要一个函数(或对函数的引用),该函数可以有选择地使用链中 promise 之前解析的值。

如果你想将一个函数作为参数传递,你必须按名称传递它

您可以将任何函数传递给 promise 回调,它将从 promise 中获取参数值并将其传递给您的函数

function s (value) {
  console.log(value);
  // expected output: 123
}
promise1.then(s);

console.log 函数与 upper s 函数相同,但它在控制台全局对象中

var console = {
   log: function(...params){ //do ... }
}