笔者在前文 作用域 、执行上下文 中介绍过作用域和执行上下文,它们是 JavaScript 中很重要的知识点,是基础中的重点,是重点中的基础。
我们讲过 JavaScript 中的作用域是词法作用域,与在哪里定义有关;而执行上下文则和调用有关,两者有关联但却是不同概念
作用域
- 作用域与哪里定义有关,在引擎编译时就知道它在哪里定义
- 其中函数作用域最为重要,因为作用域中的变量,作用域外不能访问,这起到了保护变量的作用
- 无生命周期
- 它可以理解为是“静态”的(词法作用域)
- 共全局作用域、函数作用域、块级作用域、eval 作用域
执行上下文
- 而执行上下文与调用有关
它表示一段代码执行时所带的所有信息
- 包括 this、词法环境、变量环境(ES5标准)
- 结合之前 this 所给的定义:谁调用它,this 就指向谁 就是和执行上下文相关。执行上下文也是如此,与调用者息息相关
生命周期为两个阶段
创建阶段
- 确定 this 指,即我们熟知的 this 绑定
创建变量环境
环境记录器
- 登记 var、function 等声明的变量
- 此时会发生变量提升和函数提升
对外部环境的引用(outer)
- 指向父作用域(作用域在代码执行前就确定了)
创建词法环境
环境记录器
- 登记 let、const 等声明的变量
- 会发生变量提升(hoist),但是不会被初始化,所以提前使用会报 ReferenceError,如例1所示
对外部环境的引用(outer)
- 同样指向父作用域
执行阶段
- 指向代码
- 确定作用域链
- 它则是“动态”的(与调用方相关)
- 共全局执行上下文、函数执行上下文、模块执行上下文、eval 执行上下文
例子1:
a // undefined
b // ReferenceError
c // ReferenceError
d // function d() {}
var a = 1;
let b = 2;
const c = 3;
function d(){}
var 声明变量会被初始化为 undefined,一般函数(函数声明式写法)定义会被初始化为 function xx(){}
,let、const 则不会被初始化,所以 var 定义的变量可以提前使用但指为 undefined,一般函数定义可以正常提前使用,let、const 提前使用则会报错
PS,如果使用函数表达式写法使用函数,则跟变量,如 var e = function(){} 或者 let f = () => {}
以上就是作用域和指向上下文的各种区别
系列文章
- 深入理解JavaScript——开篇
- 深入理解JavaScript——JavaScript 是什么
- 深入理解JavaScript——JavaScript 由什么组成
- 深入理解JavaScript——一切皆对象
- 深入理解JavaScript——Object(对象)
- 深入理解JavaScript——new 做了什么
- 深入理解JavaScript——Object.create
- 深入理解JavaScript——拷贝的秘密
- 深入理解JavaScript——原型
- 深入理解JavaScript——继承
- 深入理解JavaScript——JavaScript 中的始皇
- 深入理解JavaScript——instanceof——找祖籍
- 深入理解JavaScript——Function
- 深入理解JavaScript——作用域
- 深入理解JavaScript——this关键字
- 深入理解JavaScript——call、apply、bind三大将
- 深入理解JavaScript——立即执行函数(IIFE)
- 深入理解JavaScript——词法环境
- 深入理解JavaScript——执行上下文与调用栈
- 深入理解JavaScript——作用域 VS 执行上下文
- 深入理解JavaScript——闭包
- 深入理解JavaScript——防抖与节流
- 深入理解JavaScript——函数式编程
- 深入理解JavaScript——垃圾回收机制
- 深入理解JavaScript——数组
- 深入理解JavaScript——循环都来这儿
- 深入理解JavaScript——字符串
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。