延迟的 .done() 使用外部范围的变量是安全的

Is is safe for deferred .done() to use a variable from outer scope

在下面的代码中,myVar 是否总是对 done 函数可用?如果我的 deferreds 需要很长时间才能完成工作并且代码已经移动,它会知道 myVar 吗?

function doWork() {
    var deferreds = [deferredObject1, deferredObject2];

    var myVar = "Derp";    

    jQuery.when.apply(null, deferreds).done(() => {
       doStuffToMyVar(myVar);
    });
}

在更高范围内使用变量总是可以的,.done() 处理程序在这方面没有什么不同。因此,在 .done() 处理程序中使用 myVar 是完全没问题的。

你需要注意的是变量变化的时机。正如我假设您知道的那样,.done() 处理程序将在未来的某个时间被调用,并且它的确切时间可能是未知的(假设正在使用异步操作)。因此,如果有任何其他代码可以修改 myVar,您必须非常确保知道该修改可能如何与 .done() 处理程序的时间交互。

用一个极端的例子来说明这一点,这会给你带来麻烦:

function doWork() {
    var deferreds = [deferredObject1, deferredObject2];

    var myVar = "Derp";    

    jQuery.when.apply(null, deferreds).done(() => {
       doStuffToMyVar(myVar);
    });
    myVar = null;
}

因为 myVar 在调用 .done() 处理程序之前将设置为 null,因此您最终会得到 doStuffToMyVar(null),这不是您想要的.

显然还有更微妙的示例,其中在实际调用 .done() 处理程序之前 运行 函数的其他部分或其他方法可能会从您的下方更改数据。这并不意味着有任何规则不能使用来自更高范围的变量,只是你应该意识到这些类型的问题,如果它可能是你的代码中的问题,那么你可以通过制作一个有问题的变量的副本,创建一个新的闭包来传递变量,等等...