前端百题斩【012】——js中作用域及作用域链的真面目

简介: 前端百题斩【012】——js中作用域及作用域链的真面目

12.1 作用域


640.jpg

12.1.1 定义


作用域是指在程序中定义变量的区域,该位置决定了变量的生命周期。简言之作用域就是变量与函数的可访问范围,即作用域控制着变量和函数的可见性和生命周期。

12.1.2 分类


在ES6阶段之前,作用域分为两种:全局作用域和函数作用域;进行ES6之后,作用域分为:全局作用域、函数作用域和块级作用域。


  1. 全局作用域


在该作用域中的对象在代码的任何地方都能访问,其生命周期伴随着页面的生命周期。例如以下内容均在全局作用域中。


(1)window上的属性(在浏览器中)


console.log(window.location.href); // 页面地址

(2)最外层的函数


function testFun() {
    console.log('testFun');
}
testFun();

(3)最外层定义的变量


let val1 = 10;
const val2 = 20;
var val3 = 30;

(4)未定义直接赋值的变量


val4 = 40;

(5)js规定的全局对象的属性,三个值(Infinity、NaN、undefined)、九个函数(parseInt、parseFloat、decodeURI、encodeURI……)、一些构造器(Date、Array等)、四个用于当做命名空间的对象(Atomics、JSON、Math、Reflect)。


Math.sin(Math.PI / 2);;
const date = new Date();
  1. 函数作用域


在函数内部定义的变量或者函数,并且定义的变量或者函数只能在函数内部被访问。在函数执行结束之后,函数内部定义的变量会被销毁。


function test() {
    var val1 = 10;
    function fun1() {
        console.log('fun1');
    }
    console.log(val1); // 10
    fun1(); // fun1
}
test();
// console.log(val1); // val1 is not defined
// fun1(); // fun1 is not defined
  1. 块级作用域


在ES6阶段,出现了块的概念,新增了块级作用域,同时新增了let、const命令。块级作用域简言之就是使用一对大括号{}包裹的一段代码,通过单独的大括号、if块、while块、for块、try/catch/finallyd等都会产生块级作用域。(对于let和const在块级作用域的特征可见前端百题斩【002】)


// 单一括号包括的块
{}
// if语句
if (flag) {
}
// for语句
for (let i = 0; i < 10; i++) {
}
// ……


12.2 作用域链


640.jpg

12.2.1 定义


在每个执行上下文的变量环境中,都包含一个外部引用(成为outer),用来指向外部的指向上下文。当在查找一个变量的时候,如果在当前的变量环境中没有找到,js引擎会继续在outer所指向的执行上下文中查找,把这个查找的链条称为作用域链。(作用域链可以理解为一组对象列表,包含 父级和自身的变量对象,因此我们便能通过作用域链访问到父级里声明的变量或者函数。)


12.2.2 组成


作用域链由两部分组成,分别是[[scope]]属性和AO。

  1. [[scope]]属性:指向父级变量对象和作用域链,也就是包含了父级的[[scope]]和AO
  2. AO:自身活动对象,也就是该执行上下文中的变量对象。

扩展:如此 [[scope]]包含[[scope]],便自上而下形成一条 链式作用域


12.2.3 查找规则


  1. 从当前的执行作用域开始查找变量;
  2. 如果在当前作用域中找不到该变量,则向上一级进行查找;
  3. 继续向上一层查找,直到最外层的全局作用域。


12.2.4 实战


下面用一个简单的例子来演示该作用域链,以进一步理解作用域链。


var val1 = 10;
function fun1() {
    var val2 = 20;
    function fun2() {
        var val3 = 30;
        console.log(val1 + val2 + val3);
    }
    fun2();
}
fun1();


640.png


结合代码和上述执行上下文的流程图,当执行到console.log(val1 + val2 + val3);时会在fun2函数作用域中找到val3变量,在fun1函数作用域中找到变量val2,在全局作用域中找到变量val1,最终与该语句相关的三个变量均获取到。其中fun2函数作用域、fun1函数作用域、全局作用域就构成了一条作用域链。

相关文章
|
14天前
|
前端开发 JavaScript 网络协议
前端最常见的JS面试题大全
【4月更文挑战第3天】前端最常见的JS面试题大全
33 5
|
15天前
|
存储 JavaScript 前端开发
解释 JavaScript 中的作用域和作用域链的概念。
【4月更文挑战第4天】JavaScript作用域定义了变量和函数的可见范围,静态决定于编码时。每个函数作为对象拥有`scope`属性,关联运行期上下文集合。执行上下文在函数执行时创建,定义执行环境,每次调用函数都会生成独特上下文。作用域链是按层级组织的作用域集合,自内向外查找变量。变量查找遵循从当前执行上下文到全局上下文的顺序,若找不到则抛出异常。
20 6
|
30天前
|
JavaScript 前端开发 Java
纯前端JS实现人脸识别眨眨眼张张嘴案例
纯前端JS实现人脸识别眨眨眼张张嘴案例
41 0
|
17天前
|
人工智能 前端开发 JavaScript
【前端设计】HTML+CSS+JavaScript基本特性
【前端设计】HTML+CSS+JavaScript基本特性
|
27天前
|
JavaScript 前端开发
js开发:请解释什么是作用域(scope),并说明全局作用域、局部作用域和块级作用域的区别。
JavaScript中的作用域规定了变量和函数的可见性与生命周期。全局作用域适用于整个脚本,变量可通过全局对象访问,可能导致命名冲突和内存占用。局部作用域限于函数内部,每次调用创建新作用域,执行完毕后销毁。ES6引入的块级作用域通过`let`和`const`实现,变量仅在其代码块内有效,并有暂时性死区。作用域机制有助于代码组织和变量管理。
23 1
|
1月前
|
JSON JavaScript 前端开发
Node.js:前端开发的后端利器
Node.js作为一种运行在服务器端的JavaScript环境,为前端开发者打开了后端开发的大门。它以其高效的事件驱动、非阻塞I/O模型以及强大的npm生态,使得前端开发者能够轻松构建服务器端应用,实现前后端的全栈开发。本文将探讨Node.js的核心优势、应用场景以及在前端开发中的重要性。
|
1月前
|
前端开发 JavaScript 数据可视化
JavaScript:前端开发的灵魂与动力
JavaScript(JS)作为前端开发的核心语言,赋予了网页交互性和动态性。通过JS,开发者可以实现复杂的用户交互、数据操作以及动画效果,为用户带来丰富而流畅的网页体验。本文将介绍JS的基本概念、应用场景以及在前端开发中的重要性。
|
1月前
|
自然语言处理 前端开发 JavaScript
深入理解JavaScript中的闭包与作用域链
在JavaScript编程中,闭包和作用域链是两个非常重要的概念,它们对于理解代码的执行过程和解决一些特定问题至关重要。本文将深入探讨JavaScript中闭包和作用域链的原理和应用,帮助读者更好地理解这些概念并能够在实际项目中灵活运用。
|
1月前
|
JavaScript 前端开发
JS作用域与作用域链
JS作用域与作用域链
|
1月前
|
机器学习/深度学习 人工智能 前端开发
【前端】JavaScript简介
【前端】JavaScript简介
17 0