【问题标题】:How replace var to let "closure callback"如何替换 var 让“关闭回调”
【发布时间】:2021-01-26 02:08:56
【问题描述】:

在我的书中MEAN 2nd Edition

这些例子都是旧的。帮助如何将此代码带入 ES6 标准 如果我将 var 更改为 let 则代码不起作用。 我明白为什么,但是如何正确书写

function logCar(logMsg, callback){
    process.nextTick(function() {
        callback(logMsg);
    });
}

const cars = ["Ferrari", "Porsche", "Bugatti"];

for (const idx of cars){
    var message = "Saw a " + cars[idx];
    logCar(message, ()=>console.log("Normal Callback: " + message));
}


for (const idx in cars){
    var message = "Saw a " + cars[idx];
    ((msg)=>{
        logCar(msg, ()=> console.log("Closure Callback: " + msg));
    })(message);
}

【问题讨论】:

  • 定义“不起作用”。如果您在“正常回调”中谈论message 变量的值变为undefined,那实际上是一个功能。
  • 如果在第一个循环中将var 替换为let(或者更好的是const),它就等同于第二个循环的“关闭回调”示例。这就是块作用域变量的全部意义所在。
  • 顺便说一句,这本书是否已经将const 用于carsidx?这真的很奇怪。

标签: javascript node.js ecmascript-6 closures


【解决方案1】:

因为var 是函数作用域,而let 是阻塞作用域,您需要在正确的作用域中定义message,因为它是用var 定义的,而这里它是在全局作用域中(不是真的是一个很好的做法)所以这段代码应该是你编写它的方式:

function logCar(logMsg, callback){
    process.nextTick(function() {
        callback(logMsg);
    });
}

const cars = ["Ferrari", "Porsche", "Bugatti"];
let message;

for (const car of cars){
    message = "Saw a " + car;
    logCar(message, ()=>console.log("Normal Callback: " + message));
}


for (const idx in cars){
    message = "Saw a " + cars[idx];
    ((msg)=>{
        logCar(msg, ()=> console.log("Closure Callback: " + msg));
    })(message);
}

【讨论】:

    【解决方案2】:

    这段代码真的很奇怪;太多的噪音隐藏了不那么复杂的主题。

    关键问题是第一个循环本质上被打破了:线...

    for (const idx of cars)
    

    ... 不是遍历索引,而是遍历 cars 数组的 values。因此...

    var message = "Saw a " + cars[idx];
    

    ... 从不将 'Ferrari'、'Porsche' 等分配给该变量:相反,它使用这些字符串作为索引并以 undefined 结尾。

    这就是您在本地化 message(使用 letconst 时)看到的内容。这也与函数本身无关,它们将在正确的 let/const-ed message 范围内。所以这...

    for (const idx in cars) { // note that `in`
        const message = "Saw a " + cars[idx];
        logCar(message, ()=>console.log("Normal Callback: " + message));
    }
    

    ...实际上记录不同的值就好了。

    但原始代码仍然“有效”,因为 message 名称实际上在这些块之间共享:第二个循环中的 var 语句被忽略并被视为赋值表达式。因此,当logCar 开始使用回调时,它的值会被第二个循环(使用in cars,而不是of cars)覆盖。


    不过,这只是开始。虽然 logCar 预计会使用单个参数调用其回调 - 它的第一个参数的值 - 此代码中使用的所有回调都忽略了这一点。所以唯一的区别是第二个循环回调是在值上“作用域”的,而第一个使用全局变量。

    是的,看到process.nextTick 是另一种奇怪,来自过去的爆炸。这不仅使代码无缘无故地仅节点化(两个世界的效果相同;它是 JavaScript,该死!),而且它的用法 is discouraged 因为,嗯,它不是真正的 nextTick em>。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-09
      • 1970-01-01
      • 2015-01-09
      • 2013-01-08
      • 1970-01-01
      • 1970-01-01
      • 2016-10-15
      • 2020-07-05
      相关资源
      最近更新 更多