js_LHS查询与RHS查询

LHS查询与RHS查询

LR分别代表左侧与右侧,即对赋值操作的左侧与右侧出现的变量进行查询。
以代码var a=b;为例,js引擎会执行如下步骤:

  • js引擎会对赋值操作左侧的a变量进行LHS查询————即在当前作用域下查询变量a是否存在,如果存在,则忽略var声明,得到变量a的位置;如果不存在,则在当前作用域下创建该变量,并得到它的位置。
  • js引擎对赋值操作右侧的b变量进行RHS查询————即在当前作用域下查询变量b是否存在,如果存在,得到b的值。如果不存在,抛出ReferenceError错误。

RHS查询即简单地查找某个变量的值
LHS查询主要是试图获取变量的位置
以代码a=b为例,js引擎会执行如下步骤:

  • 对赋值操作左侧进行LHS查询,在当前作用域下如果查找到变量a,即得到变量a的位置。如果找不到变量a,就查找作用域链的下一个作用域,一直找到全局作用域,确定不存在的话就在全局执行环境中创建变量a,也因此,在局部执行环境中不加var声明的赋值操作可能会演变为在全局作用域下的声明和赋值操作。
  • 对代码a=b的赋值操作右侧的RHS查询同上。
  • 严格模式下禁止自动或隐式地在全局作用域下创建变量,所以严格模式下LHS查询失败,并不会创建或返回一个全局变量,而是抛出ReferenceError。
        var obj = {
            letA: function () {
                a = 7;
            }
        };
        obj.letA();
        console.log(a);//7
        'use strict'
        var obj = {
            letA: function () {
                a = 7;
            }
        };
        obj.letA();
        console.log(a);//ReferenceError: a is not defined at Object.letA

查询流程实例

        function foo(a) {
            console.log(a); //2
        }
        foo(2);
        //1.执行RHS查询,找到foo的值。
        //2.执行LHS查询,查询参数a的地址,并为其分配值2。
        //3.执行RHS查询,查询consol的值
        //4.执行RHS查询,查询log的值
        //5.执行RHS查询,查询a的值
        //6.log函数内如果有一个参数(比如arg1)用于接收a的值,那么log函数内同样要进行LHS查询(查询arg1的地址)
        function foo(a){
            var b=a;
            return a+b;
        }
        var c=foo(2);
        //1.执行LHS查询,查询C的地址
        //2.执行RHS查询,查询foo的值
        //3.执行LHS查询,查询参数a的地址
        //4.执行LHS查询,查询变量b的地址
        //5.执行RHS查询,查询a的值
        //6.执行两次RHS查询,查询变量a与b的值.

函数声明并不是变量赋值操作

你可能会倾向于将函数声明 function foo(a) {... 概念化为普通的变量声明和赋值,比如 var foofoo = function(a) {...。如果这样理解的话,这个函数声明将需要进行 LHS 查询。 然而还有一个重要的细微差别,编译器可以在代码生成的同时处理声明和值的定义,比如在引擎执行代码时,并不会有线程专门用来将一个函数值“分配给”foo。因此,将函数声明理解成前面讨论的 LHS 查询和赋值的形式并不合适

也因此函数的调用执行的是RHS查询

posted @ 2020-07-06 16:19  Syinho  阅读(257)  评论(0编辑  收藏  举报