在没有闭包/包装功能的范围内获取变量

时间:2018-01-05 20:03:24

标签: javascript php scope closures

如果我有一个随时间变化的变量并且我想保留它的特定实例,我必须将它包装在一个闭包中,如下所示:

function test(){
	var x = Math.random();
	// Is there an alternative to using the following closure:
	var printnum = (function(num){ 
		return function(){
			console.log(num);
		}
	})(this.x); // Because I think this is ugly
	
	return printnum;
}

var a = test();
var b = test();

a(); //number
a(); //same as above
b(); //different number
b(); //same as above

在PHP中,您可以使用use,如下所示:

$a = rand();
function () use ($a) {
  echo($a);
}

我真的很感激,因为你会立即看到正在注入哪个变量,它没有像js那样列在最底层:(function(b){})(a);此外,没有过多的括号。我尝试使用.apply().call()进行实验,但是他们都执行了这个函数,我只想在某个状态下注入一个变量。

我想我只是要求一种不存在的语言功能,但请证明我错了。有什么想法吗?

4 个答案:

答案 0 :(得分:2)

使用.bind()(ES5)删除包装函数并避免闭包的简单方法:

function test(){
  return console.log.bind(console, Math.random());
}

答案 1 :(得分:1)

我个人喜欢IIFE,但是"一个人的垃圾......"无论如何,你真的只需要传递一个数字的副本,这样你就不会陷入闭包变量。



function test(){
  // Because you are working with a number and JavaScript passes all arguments by value
  // a copy of the number will be passed to helper, allowing helper to "disconnect"
  // from using the number in the parent scope
  return helper(Math.random()); 
  
  function helper(num){
    return function(){ console.log(num); }
  }
}

var a = test();
var b = test();

a(); //number
a(); //same as above
b(); //different number
b(); //same as above




答案 2 :(得分:1)

你能用es6吗?如果是这样,箭头函数将给出相同的结果,但更简洁:



function test(){
	var x = Math.random();
  
	var printnum = x => () => console.log(x);
	return printnum(x);
  
    // OR you can invoke immediately:
    // var printnum = (x => () => console.log(x))(x);
    // return printnum;
}

var a = test();
var b = test();

a(); //number
a(); //same as above
b(); //different number
b(); //same as above




AFAIK,在javascript中,您必须以这种或那种方式将x传递给该函数,以避免在x的值稍后更改时打印其他内容

答案 3 :(得分:1)

不需要printnum功能。只需返回内部匿名函数。

这与PHP基本相同,但它不需要use()声明来列出要继承到闭包的变量(PHP需要这个,因为默认是不允许任何访问外部变量)。



function test() {
  var x = Math.random();
  return function() {
    console.log(x);
  }
}

var a = test();
var b = test();

a(); //number
a(); //same as above
b(); //different number
b(); //same as above