手机版

Javascript中上下文和范围的图形解释

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

执行上下文(执行上下文)

执行上下文(称为context)决定了在Js执行过程中可以获得哪些变量、函数和数据。一个程序可以分为很多不同的上下文,每个上下文都绑定了一个变量对象,就像一个容器,用来存储当前上下文中所有定义的或者可用的变量和函数。最顶层或最外层的上下文称为全局上下文,它取决于执行环境,例如节点中的全局和浏览器中的窗口:

应当注意,上下文和范围是不同的概念。Js本身是单线程的。每当执行一个函数时,都会生成一个新的上下文,这个新的上下文会被推入到Js的上下文堆栈中,并在函数执行后弹出。因此,Js解释器总是在栈顶的上下文中执行。生成新的上下文时,会先绑定上下文的变量对象,包括函数中定义的参数和变量;之后,将创建一个属于这个上下文的范围链,最后这个范围链将被赋予这个函数所属的对象。这个过程可以用下图表示:

如上所述,这被分配给函数所属的对象。具体来说,当函数在全局对中定义时,这指向全局;当函数是对象的方法时,它指向对象:

var x=1;var f=function(){ console . log(this . x);} f();//-1 var ff=function(){ this . x=2;console . log(this . x);} ff();//- 2 x //- 2var o={x: 'o's x ',f : f };o . f();//'o's x '范围链

如上所述,在函数执行时生成新的上下文时,首先绑定当前上下文的变量对象,然后创建范围链。我们知道函数的定义可以嵌套在其他函数创建的上下文中,也可以并行定义在同一个上下文中(比如全局)。实际上,作用域链是将嵌套定义的上下文绑定的所有变量对象自下而上串在一起,使嵌套函数可以“继承”上层上下文的变量,并行函数之间互不干扰:

var x='全局';函数a(){ var x='a的x ';函数b(){ var y='b的y ';console . log(x);};b();}函数c(){ var x='c的x ';函数d(){ console . log(y);};d();} a();//-' a ' s x ' c();//-引用错误: y未定义x///“全局”y //-引用错误: y未定义闭包

如果我们理解了上面提到的上下文和范围链的机制,我们就可以清楚地看到闭包的概念。每个函数在被调用时都会创建一个新的上下文和作用域链,作用域链将外部(上)上下文绑定的变量对象一一连接起来,这样当前函数就可以获取外部上下文的变量和数据。如果我们在函数中定义一个新函数,并将内部函数作为值返回,则内部函数中包含的范围链将一起返回。即使内部函数在其他上下文中执行,其内部作用域链仍然保留原始数据,而当前上下文可能无法获取原始外部函数中的数据,这使得函数内部的作用域链受到保护,从而形成“闭包”。

请看下面的例子:

var x=100var Inc=function(){ var x=0;返回函数(){ console . log(x);};};var Inc 1=Inc();var Inc 2=Inc();Inc 1();//-0 Inc 1();//-1 Inc 2();//-0 Inc 1();//-2 Inc 2();//-1x;//-100执行过程如下图所示。inc创建时返回的匿名函数生成的作用域链包含INC中的X,即使赋值给inc1和inc2后直接在全局上下文下调用,它们的作用域链仍然由定义所在的上下文决定,并且由于X是在Function inc中定义的,因此不能被外部全局上下文改变,从而实现闭包效应:

这是结案陈词

我们多次提到,执行上下文和范围实际上是由函数创建和划分的,但这在函数中不同于范围链,它是由当前执行该函数时的Object环境决定的,这也是最容易混淆和误用的一点。一般示例如下:

var name=' globalvar o={ name: 'o ',getname : function(){ return this . name } };o . getname();//-'o '因为这个由getName绑定的是在执行o.getName()时调用它的o,所以这个==o;此时;更令人困惑的是,在封闭的情况下:

var name=' globalvar oo={ name: 'oo ',GetNameFunc3360 function(){ return function(){ return this . name;};} } oo . GetNameFunc()();///“全局”当闭包函数在返回后被调用时,它相当于:

getName=oo . GetNameFunc();getName();///“全局”是一个更明显的例子:

Varooo={name:' ooo ',getname 3360 oo . getname func()//此时,这个闭包函数绑定到了新的Object };ooo . getname();///‘ooo’当然,有时为了避免在执行过程中替换闭包时出现这种情况,可以采用以下方法:

var name=' globalvar oooo={ name: 'ox4 ',getnamefnc : function(){ var self=this;return function(){ return self . name;};}};oooo . GetNameFunc()();///“ox4”或在调用时强制定义执行的对象:

var name=' globalvar oo={ name: 'oo ',GetNameFunc3360 function(){ return function(){ return this . name;};} } oo . GetNameFunc()();//- 'global' oo.getNameFunc()。bind(oo)();///“oo”摘要

Js是一种非常有趣的语言。因为它的很多特性都是针对HTML中的DOM操作的,所以比较随意,稍微有点不严谨。然而,随着前端的不断繁荣发展和Node的兴起,在jQuery时代,Js不再是一种“玩具语言”或“CSS扩展”。本文中提到的这些概念对于从传统Web开发过度开发的初学者和Js开发人员来说很容易混淆或误解。希望这篇论文能对大家有所帮助。

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