《你不知道的javaScript》上卷——第一部分——第一章——作用域是什么

王元肉==>个人主页

大家一起加油,我喜欢分专栏将知识打碎成一份一份小知识点,一篇文章只说一个知识点,因此每篇文章篇幅较短,希望大家不要介意。如有需要可以查看专栏看看是否有该文章中涉及到的知识点进行讲解的文章,如果大家觉得有帮助,希望大家三连支持一下。

推荐阅读

作用域的定义

在几乎所有的编程语言中,都会有一个功能,那就是声明变量来存储数据。那么声明的变量
存储在哪?当我们访问这个变量时,怎么快速的找到这个变量?
设计好一套规则来存储这些变量,并且之后可以方便的找到这些变量。这套规则就叫作用域。

简述编译原理

在传统的编译语言中,程序中的一段代码在执行之前都会经历三个步骤,统称为编译。
  1. 词法分析
    将字符串分解成有意义的代码块,这些代码块叫做词法单元
  2. 语法分析
    将词法单元转换成抽象语法树AST
  3. 代码生成
    将AST转换成可以执行的代码
JavaScript代码在执行之前会进行编译。

通过var a = 2;过程分析来理解作用域

首先来了解一下三个角色

  1. “引擎”——负责整个js程序的编译与运行过程
  2. “编译器”——进行语法分析与代码生成
  3. “作用域”——收集并维护所有声明的标识符变量,并提供一套存储与访问的规则。

var a = 2;运行时发生了什么?

var a = 2;会被拆解成var a; 和 a = 2;
  1. 处理var a;首先“编译器”会询问“作用域”是否已经有一个该名称的变量存在于当前作用域集合中,如果是编译器会忽略此变量声明,避免重复声明。如果否,那么就会在当前作用域集合中创建一个变量,命名为a。
  2. 处理a=2;“编译器”为“引擎”生成运行时代码,“引擎”询问作用域中是否有a这个变量,如果有会将2赋值给这个变量,否则会继续根据“作用域嵌套”查询变量a。如果没有找到则会在全局作用域中创建一个a变量。(见下方代码示例)
function fn() {
    a = 2;
}
fn();
console.log(a); // a

LHS和RHS

1、LHS:Left左,注重a = 2的左边,也就是已知有个2,要进行赋值操作时,就执行LHS查询,不会去在意a的值,只在乎要有没有a
2、RHS:Right右,注重a = 2的右边,也就是已知有个a,要知道a的值查询,就执行RHS查询,比如console.log(a),去找console对象是否有log()方法,a的值是多少
function foo(a) {
  console.log(a);
}
foo(2);
// 1、RHS查询foo变量的值,有它是一个函数
// 2、LHS查询是否有a变量,有声明再函数foo()作用域中
// 3、RHS查询console对象是否有log()方法,执行log()
// 4、RHS查询a的值是多少,输出a

作用域的嵌套

函数和{}都是块级作用域,在作用域中查找变量的过程是在当前作用域——【没找到】——>上一级作用域—【一直未没找到】——>全局作用域,找到全局作用域时,不管找没有找到都会结束查找,其中没找到会报错
function fn(a) {
  //在当前函数作用域中没找到b变量,然后去找上一级作用域(全局作用域)
  console.log(a + b);
}
var b = 2;
fn(2);//4

异常

1、如果RHS查询在所有嵌套的作用域中遍寻不到所需的变量,引擎就会抛出 ReferenceError异常
2、LHS查询时,如果在顶层(全局作用域)中也无法找到目标变量,全局作用域中就会创建一个具有该名称的变量,并将其返还给引擎,前提是程序运行在非“严格模式”下。ES5 中引入了“严格模式”严格模式禁止自动或隐式地创建全局变量。因此,在严格模式中 LHS 查询失败时,并不会创建并返回一个全局变量,引擎会抛出同 RHS 查询失败时类似的 ReferenceError 异常
3、如果RHS查询找到了一个变量,但是你尝试对这个变量的值进行不合理的操作,比如试图对一个非函数类型的值进行函数调用,或着引用 null 或 undefined 类型的值中的属性,那么引擎会抛出另外一种类型的异常,叫作 TypeError,TypeError 代表作用域判别成功了,但是对结果的操作是非法或不合理的

代码验证第1点

function fn(a) {
  // 进行RHS查询,查询不到,引擎报错ReferenceError: b is not definedat fn
  console.log(a + b);
}
fn(2);

在这里插入图片描述

代码验证第2点

{
    //非严格模式下,在当前作用域中以及全局作用域中进行LHS查询,未查询到变量a,会隐式的在全局作用域中声明变量a,并赋值
    a = 2; {
        // 找到了全局作用域中隐式添加的var a = 2;
        console.log(a); //2
    }
}
console.log(a); //2
"use strict";

{
    //严格模式下,在当前作用域中以及全局作用域中进行LHS查询,未查询到变量a,报错ReferenceError: a is not defined
    a = 2; {
        console.log(a);
    }
}
console.log(a);

在这里插入图片描述

代码验证第3点

var a = 1;
a();//TypeError: a is not a function

结束啦!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LiuJie_Boom

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值