JS:嵌套函数获取外部函数参数的副本?

时间:2012-12-09 05:42:35

标签: javascript scope nested-function

所以使用下面的代码,我向自己证明了嵌套函数确实获得了外部函数参数的副本:

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

代码产生

    742

这意味着o.f函数从匿名函数中获取a,b和c的副本。否则,我会得到undefinedundefinedundefined

我的问题是,

  • 首先,这总是如此吗?还是有严格的情况? (比如,它必须是一个物体吗?等等)
  • 此外,在javascript中还有哪些其他类型的模糊范围?我很想知道(即第三次迭代怎么样?)
  • 最后,我完全可以阅读一篇阐述javascript范围高级概念的文档。有谁知道有什么好的吗?

4 个答案:

答案 0 :(得分:9)

您观察到的是词汇范围。这意味着JavaScript中某个范围内变量的绑定取决于变量在代码中的显示位置。它总是如此,并且在任何级别都是如此。唯一的主要例外是this值,动态范围而不是词法范围。动态范围意味着函数中的变量取决于函数的调用方式和时间。 (见Lexical Scoping and Dynamic Scoping。)

示例:

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

o.a();

此示例的结果将是:

{Object o} 5
{window} 5

换句话说,第一个console.log会将this记录为o对象的引用,而第二个console.log会将this记录为windowx对象的引用。但是,两者都会将5记录为等于this。在没有上下文的非严格模式下调用window时,this的值为x。因此this不是词法范围,而是其他变量,如this。要详细了解arguments的行为,请参阅A Short Overview of this


直接回答您的问题:

1。首先,这总是如此吗?还是有严格的情况? (比如,它必须是一个物体吗?等等)

是的,除了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' 和{{1}}之外,它是正确的,它根据函数的调用方式而改变。它不必是一个对象,所有变量都是词法范围的。


2。另外,在javascript中还有哪些其他类型的模糊范围?我很想知道(即第三次迭代怎么样?)

你可以尽可能深入 - 内部函数总是可以访问其外部函数的变量。

{{1}}

这实际上是另一个被称为closures的主题的一部分,当你从另一个函数中返回一个函数时会发生这种情况。


3。最后,我完全可以阅读一篇阐述javascript范围高级概念的文档。有谁知道有什么好的吗?

我已经链接了几个资源。另一个好的:

MDN: Functions and function scope(特别是关于Nested Functions and Closures的部分)。

此外,您可以通过阅读闭包上的任何内容获益,而且您可能还想查找词汇范围

答案 1 :(得分:1)

您需要做的就是阅读闭包。 http://en.wikipedia.org/wiki/Closure_(computer_science)内部函数没有得到该变量的副本,它得到对该变量的引用。例如:

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

产量

  

842

编辑:好的,也许这不是所有,你需要阅读。我只是觉得值得证明这个概念对于许多语言来说并不陌生。

答案 2 :(得分:1)

我在代码中使用这个概念时犯了一个愚蠢的错误,错误地将参数重新声明为变量。发布在这里,以防它帮助其他人。

(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");
})();

输出:

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

答案 3 :(得分:0)

  • 是的,所有类型都适用。 javascript设计的这个元素称为“闭包”。在谷歌搜索其他阅读材料时使用它。
  • 对于您可以创建函数的嵌套程度,以及可维护性限制,没有语言限制。通常在第二级之后你会进入“关闭地狱”或“关闭意大利面”并且是时候重构了。因此,您可以嵌套4级深度的函数,并从函数4中的代码访问函数1的参数。
    • 其他2个“模糊不清”的案例浮现在脑海中:
      • 如果直接调用函数而没有明确的this绑定,则this绑定到全局(窗口)对象。这被普遍认为是javascript中一个令人震惊的缺陷。当心。
      • JavaScript具有“函数提升”,这意味着即使实际函数定义在相同范围内的源代码文件中进一步向下,也可以从作用域的顶部引用函数。
  • 阅读Douglas Crockford的JavaScript: The Good Parts。还有许多很棒的教程和在线书籍,可以通过网络搜索轻松找到。只要确保它们是现代的(大部分时间都不早于2010年)。