javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > JavaScript作用域局部全局

深度剖析JavaScript作用域从局部到全局一网打尽

作者:控心crazy

这篇文章主要为大家介绍了JavaScript作用域的深度剖析,从局部到全局一网打尽,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

JavaScript作用域深度剖析:从局部到全局一网打尽

1.1 编译原理

在传统编译语言中,一段源代码执行前会经历三个步骤:

分词/词法分析(Tokenizing/Lexing)

var a = 2;
// 分解后:
var、a、=、2、;
// 空格是否会被当做词法单元,取决于空格在这门语言中是否具有意义。

解析/语法分析(Parsing)

代码生成

1.2 理解作用域

1.2.1 演员表

1.2.2 对话

1.2.3 编译器有话说

编译器在编译过程中的第二步中生成了代码,引擎执行它时,会通过查找变量 a 来判断他是否已声明过。查找的过程由作用域进行协助,但是引擎执行怎样的查找会影响最终的查找结果。

引擎常使用的查询类型为:LHS和RHS

LHS: 赋值操作的目标是谁

RHS: 谁是赋值操作的源头

1.2.5

function foo(a) {
    var b = a;
    return a + b;
}
var c = foo(2);
// 对话:
1. 声明 var c
2. 对 c 进行 LHS
3. 对 foo(2) 进行 RHS
4. function foo(a) 期间会进行 a = 2, 对 a 进行 LHS
5. 声明 var b
6. 对 b 进行 LHS
7. 对 a 进行 RHS
8. return a + b; 分别对 a、b 进行 RHS
// 答案:
1. 所有的 LHS(一共有3处)
    1. c =..;
    2. a = 2(隐士变量分配)
    3. b = ..
2. 所有的 RHS (一共有4处)
    1. foo(2..
    2. = a;
    3. a..
    4. .. b

1.3 作用域嵌套

作用域是根据名称查找变量的一套规则。

当一个块或函数嵌套在另一个块或函数中时,就会发生作用域的嵌套。因此在当前作用域中无法找到某个变量时,引擎就会在外层作用域中继续查找,直到找到该变量,或抵达最外层的作用域(也就是全局作用域)为止。

// 非严格模式下
function foo(a) {
console.log(a + b);
}
var a = 2;
foo(2); // 4
// 严格模式下:
function foo(a) {
console.log(a + b);
}
var a = 2;
foo(2); // 4

遍历嵌套作用域链的规则:引擎会从当前的执行作用域中开始查找变量,如果找不到就会向上一级中继续查找。当抵达最外层的全局作用域时,无论找到还是没找到,查找的过程都会停止。

例子:

1.4 异常

为什么区分 LHS 与 RHS 是一种重要的事?

因为在变量还未声明(在任何作用域中都无法找到该变量)的情况下,引擎的这两种查询行为是不一样的。

// 非严格模式下:
function foo(a) {
console.log(a + b);
b = a;
}
foo(2); // 4
// 严格模式下:
'use strict';
function foo(a) {
console.log(a + b);
b = a;
}
foo(2); // ReferenceError: b is not defined

上述代码引擎行为:

第一次对 b(.. + b) 进行 RHS 查询时未找到该变量,也就是说,这是一个"未声明" 的变量,因为在任何相关的作用域都无法找到它。

第二次对 b(b = ..) 进行 LHS 查询时,如果在顶层(全局作用域)中也没找到该变量,就会在全局作用域中隐式地创建一个该名称的变量,并将其返回给引擎。

......

第一次对 b(.. + b) 进行 RHS 查询时未找到该变量,也就是说,这是一个"未声明" 的变量,因为在任何相关的作用域都无法找到它,直接抛出 'ReferenceError'。

......

1.5 小结

作用域是根据名称查找变量的一套规则。

引擎常使用的查询类型为:LHS 和 RHS

非严格模式下引擎查找规则

当引擎执行 RHS 查询在所有嵌套的作用域中找不到所需的变量,引擎就会抛出 ReferenceError 异常。

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

严格模式下引擎查找规则

ES5 引入了 "严格模式"(use strict),在行为上有很多不同,其中一个不同的行为就是严格模式下禁止自动或隐式地创建全局变量。因此在严格模式中引擎执行 LHS 查询失败时,并不会创建一个全局变量,而是直接抛出一个 ReferenceError

如果 RHS 找到了一个变量,但尝试对这个变量进行一些不合理的操作时,比如对一个非函数类型的值进行函数调用,或者引用 null 或 undefined 类型的之中属性,那引擎则会抛出另外一种类型的异常 TypeError。

特殊字符描述:

以上就是深度剖析JavaScript作用域从局部到全局一网打尽的详细内容,更多关于JavaScript作用域局部全局的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文