简体   繁体   English

寻找一些js范围的黑客

[英]Looking for some js scope hack

Here some interesting behaviour of javascript function arguments variable that you may be or maybe not aware of: 这里有一些你可能或可能不知道的javascript函数参数变量的有趣行为:

function foo(bar) {
    console.log('bar was:', bar); 
    arguments[0] = 'zap';        
    console.log('bar now:', bar); 
}  

foo('bam'); 
// bar was: bam
// bar now: zap

As you can see bar variable now pointing out to another value. 正如您所见, bar变量现在指向另一个值。

I want to make use of such behavior in a slightly strange way, I want to know is it possible to change argument value from the outside of the function scope somehow? 我想以一种稍微奇怪的方式利用这种行为,我想知道是否有可能以某种方式从函数范围的外部更改参数值?

Maybe using call/apply, or some other trycky js features? 也许使用call / apply或其他一些trycky js功能?

So I can change the value of function argument after it was called, for example: 所以我可以在调用后更改函数参数的值,例如:

function chooseNumber(number) { 
    setInterval(function() { 
        console.log('I choosed:', number) 
    }, 1000) 
}

chooseNumber(1);
// I choosed: 1
// I choosed: 1
// I choosed: 1
// ...

Then if I dicided to change my mind, how can I make so that initial function would output: 然后,如果我决定改变主意,我怎样才能输出初始函数:

// I choosed: 2
// I choosed: 2
// I choosed: 2
// ...

No, it should not be possible especially not with EcmaScript 5 strict mode. 不,特别是在EcmaScript 5严格模式下不可能。 However hackery can succeed in non-strict mode. 然而,hackery可以在非严格模式下成功。 The following tries to modify arguments within a closure via a stored arguments object; 以下尝试通过存储的arguments对象修改闭包内的arguments ; works on Firefox. 适用于Firefox。

var argsave, bar;

(function foo(a) {
    argsave = arguments;
    bar = function () {
        alert("a is now: " + a);
    };
} (13));

bar(); // --> a is 13
argsave[0] = 42;
bar(); // --> a is 42

However you do not need it, and should not use it; 但是你不需要它,也不应该使用它; if you want to modify a value within a closure, then use a function within the closure: 如果要修改闭包内的值,则在闭包内使用函数:

var setA, bar;

(function foo(a) {
    bar = function () {
        alert("a is now: " + a);
    };
    setA = function (newA) {
        a = newA;
    };
} (13));

bar(); // --> a is 13
setA(42);
bar(); // --> a is 42

A better way is to clear previous interval and then register your setInterval again with new behaviour as follows. 更好的方法是清除先前的间隔,然后再次使用新行为注册setInterval,如下所示。

function chooseNumber(number) { 
    var int = setInterval(function() { 
        console.log('I choosed:', number) 
    }, 1000) ; 
    return int;
}

var interval = chooseNumber(10);

if(someCondition ){
    clearInterval(interval);
    interval = chooseNumber(20);

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM