JavaScript
事实上是一门编译语言
。var a = 2;
// 分解后:
var、a、=、2、;
// 空格是否会被当做词法单元,取决于空格在这门语言中是否具有意义。
有状态
还是无状态
的方式进行的。简单来说,任何 JavaScript 代码片段在执行前都要进行编译(通常就在执行前)
引擎
:从头到尾负责整个 JavaScript 程序的编译及执行过程。编译器
:引擎的好朋友之一,负责语法分析及代码生成等脏活累活。作用域
:引擎的另一个好朋友,负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实行一套严格的规则,确定当前执行的代码对这些标识符的访问权限。var a = 2;
这段代码是一句声明。但会经过编译器和引擎的处理来进行。LHS和RHS
LHS: 赋值操作的目标是谁
RHS: 谁是赋值操作的源头
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
作用域是根据名称查找变量的一套规则
。当一个块或函数嵌套在另一个块或函数中时,就会发生作用域的嵌套
。因此在当前作用域中无法找到某个变量时,引擎就会在外层作用域中继续查找,直到找到该变量,或抵达最外层的作用域(也就是全局作用域)为止。// 非严格模式下
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
引擎会从当前的执行作用域中开始查找变量,如果找不到就会向上一级中继续查找。当抵达最外层的全局作用域时,无论找到还是没找到,查找的过程都会停止。
// 非严格模式下:
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
ReferenceError
'。ReferenceError
异常。"严格模式"(use strict)
,在行为上有很多不同,其中一个不同的行为就是严格模式下禁止自动或隐式地创建全局变量
。因此在严格模式中引擎执行 LHS 查询失败时,并不会创建一个全局变量,而是直接抛出一个 ReferenceError
。null
或 undefined
类型的之中属性,那引擎则会抛出另外一种类型的异常 TypeError。
ReferenceError
同作用域判断失败相关,而 TypeError
代表作用域判别成功了,但对结果的操作是非法或不合理的。LHS 和 RHS
= 操作符
在调用函数时的形参会导致关联作用的赋值操作。也就是说 foo (a, b, c...), 都会有 a = xxx, b = xxx, c = xxx ...... 的行为。LHS: 赋值操作的目标是谁
RHS: 谁是赋值操作的源头
ReferenceError
异常。"严格模式"(use strict)
,在行为上有很多不同,其中一个不同的行为就是严格模式下禁止自动或隐式地创建全局变量
。因此在严格模式中引擎执行 LHS 查询失败时,并不会创建一个全局变量,而是直接抛出一个 ReferenceError
。null
或 undefined
类型的之中属性,那引擎则会抛出另外一种类型的异常 TypeError。
ReferenceError
同作用域判断失败相关,而 TypeError
代表作用域判别成功了,但对结果的操作是非法或不合理的。
•问题标注 Q:(question)
•答案标注 R:(result)
•注意事项标准:A:(attention matters)
•详情描述标注:D:(detail info)
•总结标注:S:(summary)
•分析标注:Ana:(analysis)
•提示标注:T:(tips)