最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - JS: Nested functions gain a copy of the outer function's parameters? - Stack Overflow

programmeradmin4浏览0评论

So with the following code, I proved to myself that nested functions do indeed gain a copy of the parameters of the outer function:

    var o = {};
    (function(a,b,c,x){
        x.f = function(){
            return a.toString()+b.toString()+c.toString();
        }
    })(7,4,2,o);
    o.f();

The code yields

    742

Which means that the o.f function gains a copy of a,b, and c from the anonymous function. Otherwise, I would just get undefinedundefinedundefined

My questions are,

  • First, is this always true? or are there strict circumstances? (Like, must it be an object? etc.)
  • Also, what other kinds of obscure scopes exist like this in javascript? I'd love to know (i.e. what about third iterations?)
  • Lastly, I'd be perfectly fine with reading a document that explicates advanced concepts on javascript scopes. Does anyone know of any good ones?

So with the following code, I proved to myself that nested functions do indeed gain a copy of the parameters of the outer function:

    var o = {};
    (function(a,b,c,x){
        x.f = function(){
            return a.toString()+b.toString()+c.toString();
        }
    })(7,4,2,o);
    o.f();

The code yields

    742

Which means that the o.f function gains a copy of a,b, and c from the anonymous function. Otherwise, I would just get undefinedundefinedundefined

My questions are,

  • First, is this always true? or are there strict circumstances? (Like, must it be an object? etc.)
  • Also, what other kinds of obscure scopes exist like this in javascript? I'd love to know (i.e. what about third iterations?)
  • Lastly, I'd be perfectly fine with reading a document that explicates advanced concepts on javascript scopes. Does anyone know of any good ones?
Share Improve this question asked Dec 9, 2012 at 5:42 CodesmithCodesmith 6,7725 gold badges44 silver badges63 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 11

What you observe is called lexical scope. It means that the bindings of the variables in a certain scope in JavaScript are determined by where the variables appear in the code. It is always true, and it is true up to any level. The only main exception is the this value, which is dynamically scoped rather than lexically scoped. Dynamic scope means variables in the function depend on how and when the function is called. (See Lexical Scoping and Dynamic Scoping.)

Example:

var o = { 
    a: function() {
        var x = 5;
        console.log(this, x);
        function b() {
            console.log(this, x);
        }
        b();
    }
};

o.a();

The result of this example will be:

{Object o} 5
{window} 5

In other words, the first console.log will log this as a reference to the o object, while the second console.log will log this as a reference to the window object. However, both will log x as being equal to 5. The value of this is window when it is called in non-strict mode without a context. So this is not scoped lexically, but other variables, like x are. To read more about the behavior of this see A Short Overview of this.


To answer your questions directly:

1. First, is this always true? or are there strict circumstances? (Like, must it be an object? etc.)

Yes, it's true with the exception of this and arguments which change based on how the function is called. It doesn't have to be an object, all variables are lexically scoped.


2. Also, what other kinds of obscure scopes exist like this in javascript? I'd love to know (i.e. what about third iterations?)

You can go as deep as you want -- inner functions can always access the variables of their outer functions.

function a() {
    var x = 1;
    console.log('a:', x);
    return function b() {
        var y = 2;
        console.log('b:', x, y);
        return function c() {
            console.log('c:', x, y);
        };
    };
}

var foo = a();   // => logs 'a: 1'
var bar = foo(); // => logs 'b: 1 2'
bar();           // => logs 'c: 1 2'

This is actually part of another topic referred to as closures, which occur when you return a function from within another function.


3. Lastly, I'd be perfectly fine with reading a document that explicates advanced concepts on javascript scopes. Does anyone know of any good ones?

I've linked to a couple resources already. Another good one:

MDN: Functions and function scope (specifically the section on Nested Functions and Closures).

Also, you would be benefited from reading anything on closures, and you may also want to look up lexical scope.

I made a silly mistake while using this concept in code and wrongly re-declared the parameter as a variable. Posting here in case it helps someone else.

(function(){
var outerFunction=function(varA){
    console.debug('value of varA in outer function '+varA);
    var innerFunction = function(){
        console.debug('value of varA in inner function '+varA);
    }
    innerFunction();
};
outerFunction("hi");

var buggyOuterFunction=function(varA){
    console.debug('value of varA in buggy outer function '+varA);
    var buggyInnerFunction = function(){
        var varA = varA || "hello"; //BUG - do not redeclare
        console.debug('value of varA in buggy inner function '+varA);
    }
    buggyInnerFunction();
};
buggyOuterFunction("hi");
})();

Output:

value of varA in outer function hi
value of varA in inner function hi
value of varA in buggy outer function hi 
value of varA in buggy inner function hello
  • yes, this is true for all types. This element of the javascript design is called "closure". Use that when googling for additional reading material.
  • There are no language limits on how deeply nested you can create functions, just maintainability limitations. Generally after the 2nd level you're getting into "closure hell" or "closure spaghetti" and it's time to refactor. So you could nest functions 4 levels deep and access function 1's parameters from the code within function 4.
    • 2 other "obscure" cases e to mind:
      • If you invoke a function directly without an explicit this binding, this is bound to the global (window) object. This is universally regarded as one of the egregious flaws in javascript. Beware.
      • JavaScript has "function hoisting" which means functions can be referenced from the top of a scope even if the actual function definition is further down in the source code file within the same scope.
  • Just read Douglas Crockford's JavaScript: The Good Parts. There are also many great tutorials and online books freely available and easily found with a web search. Just make sure they are modern (written no earlier than say 2010 for the most part).

All you need to do is read up on closures. http://en.wikipedia/wiki/Closure_(puter_science) And the inner function doesn't get a copy of that variable, it gets a reference to that variable. Example:

var o = {};
(function(a,b,c,x){
    x.f = function(){
        return a.toString()+b.toString()+c.toString();
    }
    a++;
})(7,4,2,o);
o.f();

yields

842

Edit: Ok, maybe that's not all you need to need to read up on. I just figure it's worth demonstrating the concept is not foreign to many languages.

发布评论

评论列表(0)

  1. 暂无评论