💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
### ★ - 什么是作用域和作用域链 说到作用域,我们要先理解什么是**执行上下文** **执行上下文** 可以简单理解为一个对象,它具有三个类型: * 全局执行上下文(caller) * 函数执行上下文(callee) * `eval()`执行上下文 **通过代码执行过程来理解执行上下文** * 创建 **全局上下文(global EC)** * 全局执行上下文(caller)逐行以**自上而下**的顺序执行,遇到函数时,**函数执行上下文(callee)** 被`push`到执行栈顶层 * **函数执行上下文**被激活,成为`active EC`,然后开始执行函数中的代码,**全局执行上下文(caller)被挂起** * 函数执行完后,**函数执行上下文(callee)** 被`pop`移除出执行栈,控制权交回给**全局执行上下文(caller)**,继续按照自上而下的顺序执行代码 **❗ 小知识:** ~~~ 变量对象,是执行上下文中的一部分,可以抽象为一种数据作用域 其实也可以理解为一个简单的对象,存储着该执行上下文中的所有变量和函数声明(不包括函数表达式) 活动对象(AO)- 当变量对象所处的上下文被激活时(active EC)时,称为活动对象 复制代码 ~~~ #### 作用域 作用域可以理解为当前上下文中声明的**变量和函数的作用范围**,它规定了如何查找变量,也就是当前执行代码对变量的**访问权限** 作用域可以分为 **块级作用域** 和 **函数作用域** 作用域特性: * **变量提升**:一个声明在函数体内部都是可见的(仅var),函数声明由于变量声明 * **非匿名自执行函数** ,函数变量为 **只读** 状态,不能修改 ~~~ let a = function(){ console.log(1) }; (function a(){ a = 'a' console.log(a) })() // ƒ a() { a = 'a' ; console.log(a) } 复制代码 ~~~ #### 作用域链 作用域链可以理解为一组对象列表,由**当前环境与上层环境的一系列变量对象组成**,因此我们可以通过作用域链访问到父级里面声明的变量或者函数 **作用域链由两部分组成** * `[[scope]]`属性:指向父级变量对象和作用域链,也就是包含了`父级的[[scope]]`和`活动变量(AO)` * 活动变量:自身活动变量 由于`[[scope]]`包含`父级[[scope]]`形成链状关系,便自上而下形成`链式作用域` **作用域链作用** 保证当前执行环境里,有权访问的变量和函数是有序的(作用域链的变量只能向上访问变量,访问到window对象时被终止) **Ps:作用域链不允许向下访问** **作用域链和原型继承查找时的区别** - 如果去查找一个普通对象的属性,但是在当前对象和其原型中都找不到时,会返回`undefined`;但查找的属性在作用域链中不存在的话就会抛出`ReferenceError`