第一部分 第2章 词法作用域

词法作用域

词法作用域
  • 作用域查找会在找到第一个匹配的标识符时停止,内部标识符会屏蔽同名外部标识符。

  • 全局变量会自动成为全局对象(比如window或global),但这里有点小小的区别:

    var a=1;
    b=2;
    function(){
        var c=3;
        d=4;
    }
    

    若上面代码在浏览器中,全局对象是window,a,b,d都会成为window的属性,即均可以通过window.a访问(非严格模式下,严格模式下不通过var声明会报错)。
    若上面的代码在vscode中,全局对象是global,只有b,d会成为global的属性(非严格模式下,严格模式下不通过var声明会报错),global不会自动把用var声明的变量添加为自己的属性。

欺骗词法

词法作用域完全由写代码期间函数所声明的位置来定义,通过欺骗词法可以在运行时修改词法作用域,但是会导致性能下降。

  • eval(...)函数(在严格模式或ES6中被限制,不建议使用)
    接受一个字符串参数,可以在你写的代码中用程序生成代码并运行,就好像代码是写在那个位置一样。如:

    function foo(str,a){
        eval(str);
        console.log(a,b);
    }
    var b=2;
    foo("var b=3;",1);//1 3
    

    eval(...)通常用来执行动态创建的代码。

  • with关键字(在严格模式或ES6中被禁止使用)
    with通常被当作重复引用同一个对象中的多个属性的快捷方式,可以不需要重复引用对象本身。

    function foo(obj){
        with(obj){
            a=3;
        }
    }
    var o1={a:2};
    var o2={b:2};
    foo(o1);
    foo(o2);
    console.log(o1.a);//3
    console.log(o2.a);//undefined
    console.log(a);//3
    

    在上面的代码中,with会在代码执行时动态地延长作用域链(另外一个延长作用域链的方法是try-catch语句块中的catch块),因为o2没有a属性,所以通过LHS查询,引擎在全局环境创建了一个变量a并将3赋值给a,所以o2.a为undefined。

    这里有个要注意的问题就是,访问变量和访问对象的属性是不一样的:

    1. 访问变量时会LHS查询和RHS查询,在嵌套的作用域链中查询。
      赋值或者取值分别按照第一章所说的规则进行LHS查询和RHS查询
    2. 访问对象的属性则是通过对象的[[Put]]操作和[[Get]]操作来查找,在整个原型链([[prototype]]链)查找
      赋值时,通过[[Put]]操作,若变量存在则将新的值赋值给变量(实际上情况很复杂,详见第二部分第2章和第5章,p.117),若不存在,则为该对象创建该属性变量并赋值;取值时,通过[[Get]]操作取,若没有找到则遍历原型链,还是没有找到则返回undefined。

    所以上面代码改成下面的就会输出不同结果:

    function foo(obj){
        obj.a=3;
    }
    var o1={a:2};
    var o2={b:2};
    foo(o1);
    foo(o2);
    console.log(o1.a);//3
    console.log(o2.a);//3
    console.log(a);//ReferenceError: a is not defined(即a未声明undeclared)
    
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 官方中文版原文链接 感谢社区中各位的大力支持,译者再次奉上一点点福利:阿里云产品券,享受所有官网优惠,并抽取幸运大...
    HetfieldJoe阅读 6,963评论 0 11
  • 特别说明,为便于查阅,文章转自https://github.com/getify/You-Dont-Know-JS...
    杀破狼real阅读 3,593评论 0 3
  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 9,710评论 0 13
  • 一、理解js作用域 1、作用域:作用域是一套规则,用于确定在何处以及如何查找变量(标字符)。2、LHS查询:查找的...
    怀念不能阅读 3,283评论 0 1
  • “快快快,赶紧帮我发一下呗。” “这才什么时候你就买同学录了,离毕业还早呢。” “不早了好吧,就一个多月了。”……...
    权衡利弊阅读 2,454评论 4 1

友情链接更多精彩内容