使变量可用于不带闭包的异步调用

时间:2016-05-10 11:34:04

标签: javascript node.js

我是javascript的初学者。我试图找到一种解决嵌套函数的方法。看看下面的两个例子

// example 1
var x = 45;
function apple(){
    var y = 60;
    setTimeout(function(){
        console.log(y);
        console.log(x);
    }, 20);
}
apple();
console.log(x);

保持值y并在控制台上打印,因为setTimeout形成了函数apple()的闭包,并且效果很好。现在看一下下面的代码

var x = 45;
var run = function(){
        console.log(y);
        console.log(x);
}; 
function apple(){
    var y = 60;
    setTimeout(run, 20);
}
apple();
console.log(x);

我只是想单独放置函数体并将函数处理程序作为参数传递,但我坚持的事情是如何使函数apple()的变量可用于函数run(),因为它们可以不再形成封闭。是否有解决方法使其成为可能?请帮助我。

请以通用方式回答我,以便它也适用于nodejs API。我已经看到setTimeout接受了更多的参数,但我希望解决方案适用,而不管函数原型如何。

更新

很抱歉,但我认为所有答案都是使用pass by value进行函数调用。它没有实现关闭。它们获取当前y值并将其作为函数参数传递,并假设y = 80之后的setTimeout()语句如下面的代码

var y = 60;
setTimeout(run, 20);
y = 80; 

打印y = 60而不是run()内的80。我实际上想要保持y的引用而不是像闭包那样捕获它的值。谢谢

3 个答案:

答案 0 :(得分:2)

您可以使用bind

var x = 45;
var run = function(y){
        console.log(y);
        console.log(x);
}; 
function apple(){
    var y = 60;
    setTimeout(run.bind(null, y), 20);
}
apple();
console.log(x);

bind的第一个参数是你想要绑定到this的东西。之后,每个参数都传递给新创建的函数 - 请注意我将y作为参数添加到run函数。

bind给你的是一个带有预定义上下文(this)的新函数,可能还有参数的默认值。

请注意,您应该始终避免这样的情况。修改函数内部的外部变量绝不是一个好主意,它会导致很多悲伤并过早地变灰。您应该尝试重构代码,以便传递和返回值,而不是依赖引用或全局范围的变量。

答案 1 :(得分:0)

您的y变量不在run()的范围内,因此您需要将其传递给run。您还可以将run作为参数传递给apple(cb_fn) https://jsfiddle.net/stevenkaspar/ttxxpoof/

var x = 45;
var y = 80;
var run = function(){ 
  console.log('could be 80 or 85(depending on race condition): ' + y);
  console.log('should be 45: ' + x);
}; 

function apple(cb_fn){
  var y = 60; // you can declar var y again to have another ignore global y
  setTimeout(function(){
    console.log('should be 60: ' + y);
    cb_fn(); // this would be a callback function
  }, 20);
}

apple(run); // you need to pass run in as a "callback" function
console.log('should be 45: ' + x);
y = 85;
console.log('should be 85: ' + y);

答案 2 :(得分:0)

您可以使用与x相同的方法(将其设置为全局)。