admin管理员组文章数量:1401417
function a(){ return x++; }
function b(){ var x=0; return a(); /*call a using b's scope*/ };
console.log(b(),b(),b());
Desired output: 1, 2, 3
Question: is there a way to call a
inside b
, forcing it to use b
's scope?
function a(){ return x++; }
function b(){ var x=0; return a(); /*call a using b's scope*/ };
console.log(b(),b(),b());
Desired output: 1, 2, 3
Question: is there a way to call a
inside b
, forcing it to use b
's scope?
6 Answers
Reset to default 3Not quite, but you can wrap a closure around it:
(function() {
var x = 0;
window.a = function() {return x++;};
window.b = function() {return a();};
console.log(b(),b(),b());
})();
Your problem can be deposed into two parts:
- Dynamic scoping - http://en.wikipedia/wiki/Scope_(puter_science)#Dynamic_scoping
- Variable preservation across calls
The first part can be easily tackled using eval
. Read the following StackOverflow question for more details: Is it possible to achieve dynamic scoping in JavaScript without resorting to eval?
The second part requires that you store the intermediate value of the variable x
somewhere and restore it after every function call. The best place to store it in this case would be on the function b
itself.
This is what your code would look like:
function a() {
return ++x; // I believe you want prefix increment, not postfix
}
function b() {
var x = b.x;
eval(String(a)); // dynamic scoping
b.x = a();
return x;
}
b.x = 0;
console.log(b(), b(), b());
You can see the demo here: http://jsfiddle/ucGxD/1/
No. Scope es solely from how the function is defined.
You would have to pass data using arguments (and a closure) to get something from the scope of b into a.
Your exact example isn't going to work (because x
is reinitialized every time you call b
), but consider:
x = 100;
function a() { return x++; }
function b() {
var x = 0;
console.log(a(), a(), a()); // 100 101 102
eval(a.toString())
console.log(a(), a(), a()); // 0 1 2
}
Needless to say, don't try that at work.
No, there isn't. And that's definitely a feature.
Update
Since some answers and ments around here suggested using function.toString
and eval
to emulate dynamic scoping, let me summarize why I think that that is not a proper solution (besides being a bad idea anyways):
The result of invoking
toString
on functions is not specified by the language standard, nor intended for this kind of use. It happens to work on most current browsers for many (user-defined) functions, but there is no guarantee for that, and I strongly advise against writing production code that relies on it.Functions are far more than the piece of text that stringification can give you. In particular, functions are objects that have identity and carry state, neither of which stringification can preserve. More precisely:
Functions can have properties that the function body accesses (in particular, the
prototype
property). They will be lost across stringification.Functions have a closure environment encapsulating the variables from surrounding scope they use. Again, this will be lost, resulting in dangling or misbound variable references (even if that perhaps was the purpose of the exercise for some of them).
Functions have other potentially relevant properties, like their identity, a modified
__proto__
, or configuration states like being non-extensible. None of that is preserved.Not all functions are simple JavaScript source functions. They may e.g. be native, or from ES6 on, they may be function proxies. In neither case will stringification be useful.
A function with unbound variable references is not legal in strict mode (and thus will be illegal in many places in ES6).
So while stringification may work in some simple cases, that is by accident, not by design. It is a brittle hack. Steer clear of it.
Yes. Context can be transferred by call or apply. You can set the context to scope by calling bind to itself. See this example:
function a() {
return ++this.x;
}
function b() {
this.x = this.x || 0;
return a.call(this); // a works with x in b's context
}
b = b.bind(b); // now the b's context is the b's scope :-)
console.log(b(),b(),b()); // 1 2 3
console.log(x); // error: x is not defined - global scope is clear
As Quentin points out see the difference between context and scope here.
本文标签:
版权声明:本文标题:functional programming - Is there a way to dynamically modify a closure of a function in JavaScript? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744247176a2597075.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论