作用域

# 作用域

定义:一套用于确定何处以及何处查找变量的规则。

[TOC]

# 一、查询

# 1.1 LHS查询

查找用来对变量进行赋值

非严格模式:如果在全局作用域中无法找到目标变量,则会在全局作用域中创建具有该名称的变量。

严格模式:不创建全局变量,只返回ReferenceError异常。

# 1.2 RHS查询

获取变量的值

找不到变量就抛出ReferenceError错误

查询到变量,但对变量的值进行了不合理的操作,则抛出TypeError错误

# 1.3 小练习

function foo(a) {

var b = a;

return a+b;

}

var c = foo(2);
1
2
3
4
5
6
7
8
9

LHS查询有3处:c=...; a=2(隐式变量分配);b=...

RHS查询有4处:foo(2); =a; a...; b...

  • 编译器有话说:当变量出现在赋值操作的左侧时进行 LHS 查询,出现在右侧时进行 RHS 查询。
    • 讲得更准确一点, RHS 查询与简单地查找某个变量的值别无二致,而 LHS 查询则是试图找到变量的容器本身,从而可以对其赋值。
    • 从这个角度说, RHS 并不是真正意义上的“赋值操作的右侧”, 更准确地说是“非左侧”。

# 二、作用域

域:空间、范围、区域……

作用:读、写

  • script是域
    • 全局变量、全局函数
    • 自上而下(单线程)
  • 函数是域
    • 局部域
  • {}是域

# 2.1 词法作用域(lexical scoping)

  • 在定义时确定,就是写代码的时候。
  • 不在乎何时何地被调用,只关心函数被声明时所处的位置。

# 2.2 动态作用域(dynamic scoping)

  • 在调用时确定,就是代码运行的时候。
  • 不在乎如何声明以及在任何处声明的,只关心何处调用。

# 2.3 浏览器

JS解析器:先编译后执行

# 2.3.1 编译器

执行第一步:找一些东西,但不会读取。JS预解析。

# 2.3.2 引擎

执行第二步:逐行解读代码。

表达式:= + - * / % ++ -- ! 参数……

表达式可以修改预解析的值!函数声明不会改变预解析的值