视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
JavaScript中的变量查找
2020-11-27 20:23:15 责编:小采
文档

总所周知,JavaScript变量是按照作用域链来进行查找的(作用域和作用域链相关知识可参看我的另一篇文章,《基于JavaScript作用域链的性能调优》), 那么,对于一个简单的赋值操作,等号左右两边变量的查找方式一样吗?让我们从一个简单例子讲起~

console.log(a); // undefined
var a = 3;
console.log(a); // 3

console.log(b); // ReferenceError
b = 4;
console.log(b); //4

1. LHS(left-hand-side左查找)和RHS(right-hand-side右查找)

概念如下:

  • LHS查询:试图找到变量容器本身,从而可以对其进行赋值

  • RHS查询:查找某个变量的值

  • 对于一个赋值语句var a = b;,等号左侧进行LHS查询,等号右侧进行RHS查询;如果是一个普通的打印语句console.log(a),那么,查找变量a属于RHS查询。

    两者的相同之处:都遵循作用域链查找。

    2. LHS和RHS查询区别

    (1) LHS查询
    当JavaScript引擎执行LHS查询时,如果在顶层作用域中无法找到目标变量,那么,就会在全局作用域中创建一个具有该名称的变量,并将其返回给引擎(非严格模式下)。

    要注意,这种方式创建的全局变量,严格上来讲并不是真正的变量,而是全局对象的属性,可以通过delete操作符将其删除。但是,用var声明的全局变量,是不可以用delete操作符删除的。

    参考文章首部的例子:

    b = 4;
    console.log(b); // 4
    delete b;
    console.log(window.b); // undefined

    程序中并没有声明变量b,但是由于LHS查询会自动创建未找到的目标变量,所以,打印b返回4。然后删除b,可删除成功。

    如果是严格模式:

    "use strict";
    b = 4;
    console.log(b);

    这时LHS查询将无法自动创建未声明的目标变量,所以,打印b时抛出异常:Uncaught ReferenceError: b is not defined

    (2) RHS查询
    当JavaScript引擎执行RHS查询时,如果在作用域链中都无法找到目标变量,那么,引擎会抛出ReferenceError异常。

    参考文章首部的例子:

    console.log(b); 
    b = 4;

    RHS查询变量b,在全局作用域中未曾找到该变量定义,于是,引擎抛出异常Uncaught ReferenceError: b is not defined

    3. 小贴士

    (1) 变量提升
    概念:用var声明的变量,总是会被JavaScript解释器悄悄地“提升”到方法体的最顶部。

    参考文首的例子:

    console.log(a); 
    var a = 3;

    JavaScript引擎会将其解析为:

    var a = undefined;
    console.log(a); 
    a = 3;

    所以,第一次打印a时会返回undefined

    (2) ReferenceError和TypeError
    ReferenceError代表作用域判别失败,也就是作用域内查询变量失败。
    TypeError代表作用域判别成功,但是对结果的操作是非法或者不合理的。

    例如:

    foo();
    var foo = function () {
     console.log('a');
    }

    执行foo()语句时,首先RHS查找,在全局作用域中找到foo变量,值为undefined(变量提升)。
    然后以函数执行方式操作foo变量,很明显,undefined并不是一个合法函数,于是引擎抛出异常:Uncaught TypeError: foo is not a function,执行失败。

    下载本文
    显示全文
    专题