当前位置: 首页 > 科技观察

前端100题——JS中作用域和作用域链的真面目

时间:2023-03-15 20:04:58 科技观察

12.1作用域12.1.1定义作用域是指程序中定义变量的区域,位置决定了变量的生命周期。简而言之,范围就是变量和函数的可访问范围,即范围控制着变量和函数的可见性和生命周期。12.1.2分类在ES6阶段之前,作用域分为全局作用域和函数作用域两种;ES6之后,作用域分为:全局作用域、函数作用域和块级作用域。全局范围内的对象可以在代码的任何地方访问,它们的生命周期伴随着页面的生命周期。比如下面这些都是全局作用域的。(1)window上的属性(在浏览器中)console.log(window.location.href);//页面地址(2)最外层函数functiontestFun(){console.log('testFun');}testFun();(3)最外层定义的变量letval1=10;constval2=20;变量3=30;(4)未定义的直接赋值变量val4=40;(5)js指定的全局对象的属性,三个值(Infinity,NaN,undefined),九个函数(parseInt,parseFloat,decodeURI,encodeURI...),一些构造函数(Date,Array等),四个用作命名空间的对象(Atomics、JSON、Math、Reflect)。Math.sin(Math.PI/2);;constdate=newDate();函数作用域是定义在函数内部的变量或函数,定义的变量或函数只能在函数内部访问。函数执行结束后,函数内部定义的变量将被销毁。functiontest(){varval1=10;functionfun1(){console.log('fun1');}console.log(val1);//10fun1();//fun1}test();//console.log(val1);//val1isnotdefined//fun1();//fun1isnotdefined块级作用域在ES6阶段,出现了块的概念,增加了新的块级作用域,增加了let和const命令。简而言之,块级作用域就是用一对花括号{}包裹的一段代码。块级作用域会通过单独的大括号生成,if块,while块,for块,try/catch/finallyd等(块级作用域中let和const的特性见前端【002])//包含在单括号中的块{}//if语句if(flag){}//for语句for(leti=0;i<10;i++){}//...12.2作用域链12.2.1定义在每一个执行上下文的变量环境中,都有一个外部引用(outer),用来指向外部上下文。在查找变量时,如果在当前变量环境中没有找到,js引擎会在outer指向的执行上下文中继续查找,这个查找链称为作用域链。(作用域链可以理解为一组对象列表,包括父级和自身的变量对象,所以我们可以通过作用域链访问父级中声明的变量或函数。)12.2.2作用域链由二分别由[[scope]]属性和AO组成。[[scope]]属性:指向父变量对象和作用域链,包括parent的[[scope]]和AOAO:自身的活动对象,即执行上下文中的变量对象。扩展:如果[[scope]]包含[[scope]],则自上而下形成一个链式作用域。12.2.3搜索规则从当前执行范围开始搜索变量;如果在当前范围内找不到该变量,则向上查找一级;继续向上搜索一级,直到最外层的全局范围。12.2.4实战下面用一个简单的例子来演示作用域链,以进一步理解作用域链。varval1=10;functionfun1(){varval2=20;functionfun2(){varval3=30;console.log(val1+val2+val3);}fun2();}fun1();结合上述代码和执行上下文的流程图,当执行到console.log(val1+val2+val3);val3变量会在fun2函数作用域中找到,变量val2会在fun1函数作用域中找到,变量val1会在全局作用域中找到,最后用这条语句得到所有三个相关变量。其中,fun2函数作用域、fun1函数作用域和全局作用域构成一个作用域链。本文转载自微信公众号“牵着风筝”,可通过以下二维码关注。转载本文请联系风筝持有人公众号。