当前位置: 首页 > Web前端 > JavaScript

学了没用,JavaScript中的作用域和作用域链

时间:2023-03-26 21:02:39 JavaScript

什么是作用域?范围定义变量的可见性或可访问性。说白了,一个变量能否被访问或引用是由它的作用域决定的。JavaScript中有三种作用域。全局作用域函数作用域(局部作用域)块作用域letglobalVariable="我是全局作用域下的一个变量"functionfunc(){letlocalVariable="我是局部作用域下的一个变量"}if(true){letblockVariable="我是块作用域下的一个变量"}GlobalScopeGlobalScope定义在最外层的变量是在全局作用域中的,在程序的任何地方都可以访问全局作用域中的变量。varglobalVariable="Globalscopevariable"functionfunc(){//在函数内访问全局范围变量console.log("Accesswithinthefunction:",globalVariable)}func()console.log("Accessoutsidethefunction:",globalVariable)输出:函数内访问:全局作用域变量函数外访问:全局作用域变量在花括号内使用var关键字(包括纯花括号、if、while、for)的变量仍然属于`全局作用域。if(true){varglobalVariable="globalscopevariable"}console.log("externalaccess:",globalVariable)output:externalaccess:globalscopevariablefunctionscope(localscope)FunctionScope(LocalScope)变量定义在一个函数属于函数作用域,也称为局部作用域。局部范围内的变量只能在其自己的范围内访问。functionfunc(params){varlocalVariable="Localscopevariable"console.log("Internalaccess:",localVariable)}func()console.log("Externalaccess:",localVariable)//UncaughtReferenceError:localVariableisnotdefinedoutput:accesswithinthefunction:localscopevariableUncaughtReferenceError:localVariableisnotdefined例子中,我们试图从外部访问局部作用域定义的变量,报错变量未定义。BlockScopeES6中引入了let和const,区别于var。在前面的例子中,在花括号之间用var定义的变量(包括纯花括号、if、while、for)都是全局作用域。如果我们在花括号中用let和const定义,变量将在块范围内。块范围内的变量只能在它们自己的范围内访问。let和const的区别在于const定义的是常量,不能修改定义的值。{letblockVariable="Blockscopevariable"console.log("Internalaccess:",blockVariable)}console.log("Externalaccess:",blockVariable)//UncaughtReferenceError:blockVariableisnotdefined输出:块内访问:BlockscopevariableUncaughtReferenceError:blockVariableisnotdefined例子中我们试图从外部访问blockscope中定义的变量,报错变量未定义。什么是作用域链?ScopeChain当一个变量在当前作用域内找不到时,会尝试寻找它的外层作用域。如果找不到,它会继续往外找(只往外找,不找兄弟作用域,更不会往里找)。这种类似链的查找规则称为作用域链。letvariable1="Iamvariable1,external"letvariable2="Iamvariable2"functionfunc(){letvariable1="Iamvariable1,internal"{letvariable3="Iamvariable3"}{//向外搜索,在上一层函数中找到console.log(variable1)//向外搜索,直到全局作用域console.log(variable2)//找不到,报错console.log(variable3)//UncaughtReferenceError:variable3isnotdefined}}func()output:Iisvariable1,andtheinternalisvariable2UncaughtReferenceError:variable3isnotdefined例子中打印variable1变量时,发现在上层作用域,即函数,如果找到variable1变量,就会停止查找,不会找到全局作用域下的variable1变量。在找variable2变量的时候,在upper作用域中没有找到,所以一直找到upper和upper作用域,也就是全局作用域下的variable2变量。在查找variable3变量时,由于variable3变量定义在brother作用域中,所以不会查找到,因为作用域链的规则是只查找上层作用域,不查找brother作用域。所以这里报了变量undefined的错误。一个函数的作用域是在它被定义的时候,而不是在它被调用的时候="Iamthevariableinsidecurlybraces"letfunc2=func()func2()}输出:Iamthevariableinsidefunc例子中,执行func2函数时要查找的作用域就是定义func2时的作用域,不是调用的范围。如果找不到变量会怎样?如果直到全局范围才找到变量,则执行以下操作。非严格模式:全局变量的隐式声明严格模式:报错非严格模式在非严格模式下,当试图给一个变量赋值时,如果找不到,就会将其隐式声明为全局变量。{variable="Iamanimplicitlydeclaredvariable"}console.log(variable)output:Iamanimplicitlydeclaredvariable在上面的例子中,variable被隐式声明为全局作用域,因为它没有声明下面的变量,这使得可以在最外层打印出变量variable的值。在非严格模式下,当试图使用一个变量的值时,找不到也会报错。{console.log(variable)//UncaughtReferenceError:variableisnotdefined}Output:UncaughtReferenceError:variableisnotdefined上面的例子中,因为使用时没有定义variable,所以报undefined错误。严格模式加上“usestrict”表示是严格模式。在严格模式下,无论赋值还是使用没有事先声明的变量都会报错。"usestrict"{variable="Iamanimplicitlydeclaredvariable"//UncaughtReferenceError:variableisnotdefined}输出:UncaughtReferenceError:variableisnotdefined作用域的好处?防止命名冲突:您编写了一个10,000行的代码文件。如果没有作用域,就得给每个变量起一个唯一的名字,想想也是一种折磨。安全性:变量不会被外部访问,保证变量值不会被随意修改。如果你在函数中定义的变量在几千行之后还能被不小心修改,想想就很折磨人。更高级的语法:封装、面向对象等的实现都离不开变量的隔离,这是通过作用域来实现的。说英语!编写代码时,不需要区分全局作用域、局部作用域和块作用域的概念。请记住,花括号是一个范围,查找变量总是从内到外。现在我们的编辑器基本都有缩进格式了,从当前代码块的位置往左,就是它能引用的所有变量。比如我们每个家庭都是一个scope。当我们需要手术费而付不起的时候,首先要在家里自己找,向父母、兄弟姐妹请教,不要向其他陌生人求助。家庭。如果没有,就在熟人关系范围内出去问问。如果还是不行,可以向街道居委会求助。居委会没有办法向国家求助。从最近的关系开始,逐层往外走,这就是作用域和作用域链。最后,强烈建议大家使用let命名变量,放弃var!