手机版

详细解释JavaScript范围和范围链

时间:2021-08-26 来源:互联网 编辑:宝哥软件园 浏览:

前言

JavaScript中有一个特性叫做范围。虽然对于很多新手开发者来说,范围的概念并不容易理解,但我会尽量用最简单的方式来解释范围和范围链。希望大家有所收获!范围

1.什么是范围

范围是运行时代码的某些部分中变量、函数和对象的可访问性。换句话说,范围决定了代码块中变量和其他资源的可见性。可能这两句不太好理解。我们先来看一个例子:

函数out fun 2 () {var invisible='内部变量2 ';} outun2();//必须先执行这个函数,否则不知道里面是什么console . log(InTerface);//未知引用错误:不变量没有定义从上面的例子中,我们可以理解范围的概念。变量“不变”没有在全局范围内声明,因此在全局范围内取值会报告错误。我们可以这样理解:范围是一个独立的领地,这样变量就不会泄露或暴露。也就是说,作用域最大的用处就是隔离变量,同名的变量在不同的作用域下不会冲突。

在ES6之前,JavaScript没有块级作用域,只有全局作用域和函数作用域。ES6的到来为我们提供了“块级范围”,这可以通过添加命令let和const来体现。

2.全球范围和职能范围

可以在代码中任何地方访问的对象都具有全局范围。一般来说,以下情况具有全局范围:

最外面的函数和在最外面的函数之外定义的变量具有全局范围

Var outVariable='我是最外面的变量';//最外面的变量函数outFun() {//最外面的函数var InTerface='内部变量';函数innerFun() {//内层函数console . log(InTerface);} innerFun();} console . log(OutVariable);//我是最外面的变量outFun();//内部变量console . log(InTerface);//不变不是definedinnerFun();//未定义innerFun。所有没有定义直接赋值的变量都被自动声明为具有全局作用域

函数outun2(){变量='未定义直接赋值变量';Var inVariable2='内部变量2 ';} outun2();//必须先执行这个函数,否则不知道里面是什么console.log(变量)。//没有定义直接赋值的变量console . log(inviable2);//未定义变量2窗口对象的所有属性都具有全局范围

通常,窗口对象的内置属性具有全局范围,如window.name、window.location、window.top等。

全局范围有一个缺点:如果我们写了很多行JS代码,变量定义没有被函数包含,那么它们都在全局范围内。这将污染全局命名空间,并容易导致命名冲突。

//vardata={a: 100}在张三写的代码中,var data={x: true}在李四写的代码中,这就是为什么jQuery、Zepto等库的所有代码都放在(function () {中.}) ().因为里面的所有变量都不会泄露暴露,不会污染外部,也不会影响其他库或者JS脚本。这是功能范围的体现。

函数范围是指在函数内部声明的变量。与全局范围相反,局部范围通常只能在固定的代码片段中访问,最常见的是在函数内部。

函数do something () {varblog name='去浪中划船';函数innerSay(){ alert(blogName);} innerSay();} alert(Blogname);//脚本错误innerSay();//Script错误范围是分层的,内部范围可以访问外部范围的变量,否则不能。举个例子吧。使用气泡可能更容易理解范围:

最终的输出结果是2、4和12

Bubble 1是一个带有标识符foo的全局范围;Bubble 2是带有标识符a、bar和b的作用域fooBubble 3是只有标识符c的作用域栏,值得注意的是,block语句(大括号“{}”之间的语句,如if和switch条件语句或for和while循环语句)不会像函数一样创建新的作用域。块语句中定义的变量将保留在其现有范围内。

If (true) {//'if '条件语句块不会创建新的作用域var name=' Hammad//名称仍在全局作用域}console.log(名称)中;//日志‘Hammad’js的初学者经常需要花一些时间来习惯变量提升,但是如果不理解这种独特的行为,可能会导致bug。正因为如此,ES6引入了块级作用域,使得变量的生命周期更加可控。

3.块级范围

块级范围可以通过添加命令let和const来声明,声明的变量不能在指定块的范围之外访问。块级范围是在以下情况下创建的:

函数内部和代码块内部(由一对花括号包装)的let声明的语法与var的一致。您基本上可以使用let代替var来声明变量,但是它会将变量的范围限制在当前代码块内。块级范围具有以下特征:

声明变量不会被提升到代码块的顶部。let/const声明不会被提升到当前代码块的顶部,因此您需要手动将let/const声明放在顶部,以便变量可以在整个代码块中使用。

函数getValue(condition){ if(condition){ let value=' blue ';返回值;} else {//value在此处不可用;返回null}//此处没有值}禁止重复声明。如果在代码块中定义了一个标识符,使用相同的标识符在该代码块中声明一个字母将导致引发错误。例如:

var计数=30;让计数=40;//不清楚的语法错误:标识符“count”已经声明在此示例中,count变量声明了两次:一次使用var,一次使用let。因为let不能在同一范围内重复声明现有的标识符,所以这里的let声明将引发错误。但是,如果在嵌套范围内使用let声明同名的新变量,则不会引发错误。

var计数=30;//如果(条件){let count=40,则不会引发错误;//其他代码}循环中绑定块作用域的神奇用法。开发人员可能最想实现for循环的块级范围,因为声明的计数器变量可能仅限于循环。例如,在JS中经常会看到以下代码:

button test 1/button button test 2/button button test 3/button script type=' text/JavaScript ' varb tns=document . getelementsbytagname(' button ')for(var I=0;i btns.lengthI) {btns [I]。onclick=function(){ console . log(' no . '(I ^ 1)' no . ')} }/script我们需要实现这样的需求。点击一个按钮,提示‘第n个按钮被点击’。在这里,我们不首先考虑事件代理,但从不期望点击任何按钮。怎么修改呢,最简单的就是用字母来声明我

for(设I=0;i btns.lengthI) {btns [I]。onclick=function () {console.log('编号'(i 1)'编号')}}范围链

1.什么是自由变量

首先,知道什么是自由变量。在下面的代码中,console.log(a)想要获取一个变量,但是在当前范围(比较b)中没有定义a。当前范围内没有定义的变量,成为自由变量。如何得到自由变量的值是——。从父范围查找(注意:这个语句不严格,下面会详细解释)。

Var A=100函数fn () {var B=200 console.log (a)//A这里有一个自由变量console.log(b)}fn()2。什么是范围链

没有父母怎么办?一层一层往上看,直到找到全局范围,然后放弃。这种逐层关系就是范围链。

var A=100 function f1(){ var B=200 function F2(){ var C=300 console . log(A)//自由变量,沿作用域链查找console.log(b) //来自父作用域的自由变量,沿作用域链查找console.log(c) //此作用域的变量} F2()

至于自由变量的值,提到应该取自父范围。事实上,有时这种解释会导致歧义。

Var x=10函数fn(){控制台。log (x)}函数show(f){ var x=20(function(){ f()//10,不是20 })()}show(fn)在fn函数中,取自由变量x的值时,应该取哪个范围?——应该取自创建fn函数的范围,无论fn函数将在哪里调用。

所以,不要用它来形容。相比之下,这句话更适合描述将要创建函数的域。

范围,这里强调的是“创建”,而不是“调用”,记住——实际上是所谓的‘静态范围’

var a=10 function fn(){ var b=20 function bar(){ console . log(a b)//30 } return bar } var x=fn(),b=200x ()//bar () fn()返回bar函数,赋给x. Execute x(),即执行bar函数代码。取b值时,直接在fn范围内取出。取A的值的时候,我尝试在fn范围内取,但是拿不到。我不得不转向创建fn的范围并找到它,所以最终结果是30

范围和执行上下文

许多开发人员经常混淆范围和执行上下文的概念,并把它们误认为是同一个概念,但事实并非如此。

我们知道JavaScript是一种解释性语言,JavaScript的执行分为解释和执行两个阶段,做的事情不同:

解释阶段:

词汇分析语法分析范围规则决定执行阶段:

创建执行上下文执行函数代码垃圾收集JavaScript解释阶段将确定作用域规则,因此作用域是在定义函数时确定的,而不是在调用函数时确定的,而是在执行函数之前创建的执行上下文。执行上下文最明显的一点是,它的方向是在执行过程中确定的。作用域访问的变量由编写的代码的结构决定。

作用域和执行上下文最大的区别在于执行上下文是在运行时确定的,随时可能发生变化;范围在定义时确定,不会改变。

一个范围可能包含几个上下文。有可能从来没有上下文(函数从来没有被调用过);调用函数后,上下文环境可能已被破坏。同时可能有一个或多个(闭包)。在相同的作用域下,不同的调用会产生不同的执行上下文,进而产生不同的变量值。

以上是边肖介绍的JavaScript范围和范围链的详细讲解和整合,希望对大家有所帮助。如果你有任何问题,请给我留言,边肖会及时回复你。非常感谢您对我们网站的支持!

版权声明:详细解释JavaScript范围和范围链是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。