javascript函数内部范围

考虑下面的代码:

function nepaliBuddha() {
    var a = 20;

    return function buddhaNepal() {
        console.log(a); 
    }
}

var closure = nepaliBuddha();

closure(); // logs 20
  • 现在当我们调用closure输出是20 。 这证明内部作用域属性( [[scope]]被分配给内部函数,在该内部函数中定义或声明了内部函数。如果未在声明中分配此属性,则无法在调用时记录20不同的背景

  • 调用closure()函数上下文的作用域链在函数调用时创建,由当前上下文的激活对象或VO和此函数的内部[[scope]]属性组成。

  • 调用还会创建[[scope]]属性,这意味着内部范围属性是在声明和执行时创建的吗?

  • 通常这个定义说[[scope]]属性是在运行时或函数调用时创建的,但是这并不正确,因为[[scope]]属性也已经在声明中分配了。

  • 我认为[[scope]]属性可能在执行函数后得到更新,是吗? 请给出[[范围]]内部财产的明确定义。 如何以及何时在声明时或执行时或两次创建它。


  • 哇,你不完全困惑。 好吧,我会尽可能简单地解释闭包。

    首先,我们将从范围开始。 有两种类型的范围:

  • 块范围
  • 功能范围
  • 块范围在程序中出现时立即开始。 另一方面,函数范围直到函数被调用才开始。 因此,多次调用同一个函数会导致多个作用域被创建。

    JavaScript没有块范围。 它只有功能范围。 因此,要模拟一个块范围,我们需要创建一个函数表达式并立即执行它。 这个patttern被称为立即调用的函数表达式(IIFE),它看起来像这样:

    (function () {
        // this is the JS equivalent of a block scope
    }());
    

    除了块范围和功能范围之外,还有另一种分类范围的方法。 因此我们也有:

  • 词汇范围
  • 动态范围
  • 此区别仅适用于函数作用域,因为块作用域始终在词汇范围内。 JavaScript只有词法范围。

    为了理解词法作用域和动态作用域之间的区别,我们需要理解自由和约束变量之间的区别。

  • 一个自由变量是一个在函数中使用但在该函数内没有声明的变量。
  • 据说在函数内声明的变量被绑定到该函数。
  • 考虑以下程序:

    function add(x, y) {
        return x + y; // x and y are bound to add
    }
    

    在上面的程序中,变量xy绑定到函数add,因为它们是在add中声明的。

    在另一方面变量xy在下面的程序是免费的范围内的功能add ,因为它们不是内声明add ,但他们中使用add

    function add() {
        return x + y; // x and y are free within add
    }
    

    现在自由变量是一个问题。 他们需要被映射到某个值,但是哪个值? 这就是词汇和动态范围出现的地方。 我不会介绍主要细节,但是您可以在维基百科上阅读它。

    范围很像原型继承。 当一个新的范围开始时,它从父范围继承,形成一个范围链,就像JavaScript中的原型链一样。

    词法范围和动态范围因新范围继承的父范围而异。

  • 在词汇范围界定中,一个新的功能范围继承于定义该功能的范围(即其词汇环境)。
  • 在动态范围中,新的函数范围继承自调用函数的范围(即调用范围)。
  • 由于JavaScript只有词法范围,所以我们不会为动态范围而烦恼。 考虑以下程序:

    var count = 0;
    
    function incrementCount() {
        return ++count;
    }
    
    (function () {
        var count = 100;
        alert(incrementCount()); // 1
    }());
    

    这里的函数incrementCounter有一个自由变量 - count 。 由于JavaScript具有词汇范围count因此将映射到全局变量count而不是在IIFE中声明的本地count 。 因此incrementCount返回1而不是101

    现在关闭只适用于有词汇范围的语言。 考虑以下程序:

    function getCounter() {
        var count = 0;
    
        return function () {
            return ++count;
        };
    }
    
    var counter = getCounter();
    
    alert(counter()); // 1
    alert(counter()); // 2
    alert(counter()); // 3
    

    在上面的程序中, getCounter返回的函数是关于变量count的闭包,因为:

  • 变量count在返回的函数(即counter )内是空闲的。
  • 该函数被移到声明count的范围之外。
  • 这两个条件对于称为闭包的函数都是必需的。 有关更多信息,请阅读以下答案:https://stackoverflow.com/a/12931785/783743

    现在需要了解的重要一点是,尽管函数counter可能永远不会被调用,但它仍然会被称为闭包。 闭包只是一个关闭变量的函数(称为闭包的上值)。

    当我们调用getCounter我们创建一个新的作用域(让我们调用这个作用域A ),每次我们调用getCounter (即counter )返回的函数时,我们创建一个继承范围A的新作用域。 就这样。 没有创建新的封闭。


    closure是一种特殊的对象,它结合了两件事:函数和创建该函数的环境。 环境由创建闭包时 范围内的任何局部变量组成。

    function makeFunc() {
        var name = "Mozilla";
        function displayName() {
            alert(name);
        }
        return displayName;
    }
    

    现在调用makeFunc()

    var myFunc = makeFunc();
    myFunc();
    

    在这种情况下, myFunc是一个闭包,它包含了displayName函数和创建闭包时存在的“Mozilla”字符串,即MDN

    所以,当我调用var myFunc = makeFunc();时, scope创建了var myFunc = makeFunc();myFunc()makeFunc()调用的结果)现在是一个闭包。 所以,去那里的第一行

    closure是一种特殊的对象,它结合了两件事:函数和创建该函数的环境。

    现在考虑这些

    function nepaliBuddha() {
        var a = 1;
        return function buddhaNepal() {
            a = a+1;
            console.log(a);  
        }
    }
    var closure1 = nepaliBuddha(); // An individual scope
    var closure2 = nepaliBuddha(); // An individual scope
    
    closure1(); // 1 
    closure1(); // 2
    
    closure2(); // 1
    closure2(); // 2
    closure2(); // 3
    

    演示。

    这意味着, closure1()closure2()被关闭和两者都有自己的个人范围/环境,他们已经获得自己的范围,一旦他们得到它(在这种情况下,每次通话时间nepaliBuddha你正在创建一个封闭,并给予/保存到一个变量)。

    范围定义了功能,变量等可用的区域。 所以,当你在nepaliBuddha (外部函数)中定义/声明了函数buddhaNepal (内部函数)时, buddhaNepal (内部函数)已经与全局范围分开,没有别的。 它不能访问全局范围内的任何东西,但它有自己的范围,就是这样。 nepaliBuddha (外部函数)是buddhaNepal (内部函数)的边界,在这种情况下, nepaliBuddha外部函数的局部范围/环境是buddhaNepal (内部函数)的全局范围。

    在JavaScript中,这被称为Lexical ScopeingLexical Scopeing它定义了如何在嵌套函数中解析变量名。 Lexical Scope的其他名称是静态范围界定或关闭。 这意味着内部函数的作用域包含父函数的作用域。

    链接地址: http://www.djcxy.com/p/52035.html

    上一篇: javascript function internal scope

    下一篇: Is it true that every function in JavaScript is a closure?