最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Js 词法作用域

    正文概述 掘金(Hollow)   2021-06-18   466

    词法作用域(Lexical Scope)

    词法作用域(Lexical Scope)是 JavaScript 所采用的作用域模型 . 词法作用域也称为静态作用域.

    相应定义:

    1."functions are executed using the variable scope that was in effect when they were defined, not the variable scope that is in effect when they are invoked" - according to JavaScript Definition Guide.

    ​ 函数的执行依赖于函数定义的时候所产生的变量作用域, 而不是函数调用的时候产生的。

    2.Lexical Scoping defines how variable names are resolved in nested functions: inner functions contain the scope of parent functions even if the parent function has returned(closure). - according to stackoverflow answer

    ​ 词法作用域定义了如何在嵌套函数中解析变量名:即使父函数已返回,内部函数仍包含父函数的作用域。

    3.programming ("static scope") In a lexically scoped language, the {scope} of an {identifier} is fixed at {compile time} to some region in the {source code} containing the identifier's declaration. This means that an identifier is only accessible within that region (including procedures declared within it).

    程序(“静态范围”)在词法作用域语言中,{identifier} 的 {scope} 在 {compile time} 就固定到 {source code} 中,包含标识符声明的某个区域。这意味着标识符只能在该区域内访问(包括在其中声明的过程)。

    4.In lexical scoping (and if you're the interpreter), you search in the local function (the function which is running now), then you search in the function (or scope) in which that function was defined, then you search in the function (scope) in which that function was defined, and so forth.

    "Lexical" here refers to text, in that you can find out what variable is being referred to by looking at the nesting of scopes in the program text.

    在词法范围(如果你是解释器)中,你在当前函数(现在正在运行的函数)中搜索,然后在定义该函数的函数(或作用域)中搜索,然后在定义该函数的函数(作用域)中搜索,依此类推。

    “词法”在这里指的是上下文,因为您可以通过查看程序上下文中作用域的嵌套来找出所引用的变量。

    静态作用域:

    var a = 2;
    
    function foo() {
        console.log(a);	// 输出 2 静态作用域
    }
    
    function bar() {
        var a = 3;
        foo();
    }
    bar();
    

    执行 foo 函数,先从 foo 函数内部查找是否有局部变量 a,如果没有,就查找全局变量,也就是 a 等于 2,所以结果会打印 2。

    动态作用域:

    // 伪代码
    var a = 2;
    function foo() {
        print a;	// 输出 3 而不是2 !动态作用域关注函数从何处调用,其作用域链是基于运行时的调用栈的。
    }
    
    function bar() {
        var a = 3;
        foo();
    }
    
    bar();
    

    执行 foo 函数,依然是从 foo 函数内部查找是否有局部变量 a。如果没有,就从调用函数的作用域链,也就是 bar 函数内部查找 a 变量,所以结果会打印 3。

    作用域查询:

    Lexical scope means that in a nested group of functions, the inner functions have access to the variables and other resources of their parent scope. This means that the child's functions are lexically bound to the execution context of their parents.

    词法作用域意味着在一组嵌套的函数中,内部函数可以访问其父作用域的变量和其他资源。 这意味着子函数在词法上绑定到其父函数的执行上下文。

    var name = "outer";
    function one() {
      var name = "middle";
      var other = "findme";
      function two() {
        var name = "inner";
        // Here `name` is "inner" and `other` is "findme"
        console.dir({name: name, other: other});
      }
      two();
      // Here `name` is "middle" and `other` is "findme"
      console.dir({name: name, other: other});
    }
    
    one();
    // Here `name` is "outer" and `other` is not defined.
    console.dir({name: name});
    console.dir({other: other});
    
    Js 词法作用域

    一旦找到第一个匹配,作用域查询就停止了。相同的标识符名称可以在嵌套作用域的多个层中被指定,这称为“遮蔽(shadowing)”(内部的标识符“遮蔽”了外部的标识符)。无论如何遮蔽,作用域查询总是从当前被执行的最内侧的作用域开始,向外/向上不断查找,直到第一个匹配才停止。但是从外部看内部的变量是未被定义的

    在不同执行上下文中具有相同名称的变量从执行堆栈的顶部到底部依次获得优先级。最内层函数中(执行堆栈的最顶层上下文)相同的名称将具有更高的优先级

    Another:

    function grandfather() {
        var name = 'Hammad';
        // 'likes' is not accessible here
        function parent() {
            // 'name' is accessible here
            // 'likes' is not accessible here
            function child() {
                // Innermost level of the scope chain
                // 'name' is also accessible here
                var likes = 'Coding';
            }
        }
    }
    

    词法作用域是向前工作的,这意味着 name 可以通过其子级的执行上下文访问。

    但它不会向后返回到其父项,这意味着它的父项无法访问变量 likes

    AST直观理解

    back to the example of static scope

    var a = 2;
    
    function foo() {
        console.log(a);	
    }
    
    function bar() {
        var a = 3;
        foo();
    }
    bar(); // 2
    

    Js 词法作用域

    由图可知, 程序由四部分组成. 全局作用域下包含了变量声明 VariableDeclaration, 函数function foo(), 函数function bar(), 和执行语句 ExpreesionStatement( bar() ).

    Js 词法作用域

    变量声明部分, 在全局作用域中声明变量 identifier(a), 并将 2 赋值于a.

    Js 词法作用域

    函数function foo() 部分. 其中执行 console.log(a)

    Js 词法作用域

    函数function bar()部分.

    注意到在bar的函数作用域中, 又有一个新的 变量声明 identifier(a) , 并将 3 赋值于 a.

    执行 foo()

    Js 词法作用域

    最后执行语句 ExpreesionStatement(bar () )

    由于foo函数并不是在bar函数的嵌套函数内, 所以变量 a 在foo函数作用域中找不到此变量, 接着便直接从全局变量中寻找, 并找到2.

    嵌套函数

    var value = 1;
    function bar() {
        var value = 2;
        function foo() {
            console.log(value);
        }
        foo()
    }
    bar() // 2
    

    如果为嵌套函数的话, 则将从当前子作用域依次向父作用域查找, 直到找到第一个value值(2)结束.

    function bar() 部分的AST 如下:

    Js 词法作用域

    变量污染

    var a = 2;
    function foo() {
        console.log(a);
    }
    function bar() {
        a = 3;
        foo()
    }
    bar() // 3
    console.log(a) // 3
    

    还是重点注意 function bar() 部分的AST:

    Js 词法作用域

    在这里并不再是变量声明 (VariableDeclaration)了, 而是 执行语句(ExpressionStatement). 因此执行bar函数的时候, 首先根据上下文顺序将 3 赋值于全局变量 a, 并通过foo函数 查找到全局变量 a = 3, 打印出了3. 局部变量修改了全局变量, 造成了变量污染. 这段代码也可以看作是在 function bar()函数作用域中再次(用var)声明了 a , 并将 3 赋值于 a, 而var 声明并没有块作用域的概念, 结果便是在全局作用域中创建了 a 变量. 如图所示:

    Js 词法作用域

    这句 a = 3 具有神秘感 ! 让我验证了1个小时, 它究竟是什么, 还得不出结论..

    REF: ​ Lexical Scope:

    ​ stackoverflow.com/questions/1…

    ​ howtonode.org/what-is-thi…

    ​ www.gnu.org/software/gu…

    ​ wiki.c2.com/?LexicalSco…

    ​ wiki.c2.com/?DynamicSco…


    起源地下载网 » Js 词法作用域

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元