JavaScript是一种脚本语言,支持高级功能,如函数式编程、闭包和基于原型的继承。刚开始的时候,JavaScript看似很容易上手,但是随着使用的深入,你会发现JavaScript其实很难掌握,一些基本概念简直不可思议。JavaScript中的这个关键词是一个很容易混淆的概念。在不同的场景中,这将体现不同的对象。有一种观点认为,只有在JavaScript中正确掌握了这个关键词,才能被认为是踏入了JavaScript的门槛。在主流的面向对象语言(如Java、C#等)中。),这个的意思是明确具体的,也就是它指向当前的对象。通常在编译时绑定。在JavaScript中,这是在运行时绑定的,这也是JavaScript中这个关键字具有多重含义的本质原因。
由于JavaScript在运行时的绑定属性,这在JavaScript中可以是全局对象、当前对象或任何对象,这完全取决于如何调用函数。在JavaScript中调用函数有几种方式:作为对象方法调用、作为函数调用、作为构造函数调用,以及使用apply或call调用。俗话说,文字不如表格,但表格不如数字。为了让人们更好地理解JavaScript这指向了什么。用下图解释:
上图叫做JavaScript这个决策树’(在非严格模式下)。下面的例子说明了这个图表如何帮助我们做出判断:
var点={ x : 0,y : 0,moveTo :函数(x,y){ this . x=this . x x;this . y=this . y y;} };//决策树解释:point.moveTo(1,1)函数没有被new调用,所以输入no decision//如果它是由点()调用的。),它指向之前的调用对象。moveTo,即point.moveTo(1,1);//这是绑定到当前对象,也就是点对象。通过point.moveTo()函数在“JavaScript这个决策树”中判断的过程如下:
1)是用new调用的point.moveTo函数吗?这显然不是。转到“否”分支,即函数是否用点()调用。)?
2)point . move to函数用点(.)调用。),也就是它走到了“是”的分支,也就是这里指向的对象点先于点。moveto
下图显示了点移动到函数的解析图:
再举一个例子,看看下面的代码:
函数func(x){ this . x=x;} func(5);//这是全局对象窗口,x是全局变量。//决策树分析:func()函数是用new调用的吗?如果没有,是否用点号调用了entering func()函数?否则,这指向全局对象窗口x;//x=5func()函数在JavaScript this决策树’中判断如下:
1)func(5)函数是否用new调用?这显然不是。转到“否”分支,即函数是否用点()调用。)?
2)func(5)函数不是用点()调用的。),即转到“否”分支,即这里指向全局变量window,所以this.x实际上就是window . x;
下图显示了说明此函数指向什么的分析图:
作为直接调用函数的一种方式,让我们看一个复杂的例子:
Varpoint={x: 0,y: 0,移至:函数(x,y){//内部函数var moveX=函数(x){ this . x=x;//这说明了什么?窗口};//内部函数var moveY=函数(y){ this . y=y;//这说明了什么?窗口};moveX(x);moveY(y);} };point.moveTo(1,1);point.x//=0点. y;//=0x;//=1y;//=1point.moveTo(1,1)实际上是在内部调用moveX()和moveY()函数,在JavaScript这个决策树’中判断这个moveX()函数内部的过程如下:
1)movex(1)函数是用new调用的吗?这显然不是。转到“否”分支,即函数是否用点()调用。)?
2)movex(1)函数不是用点()调用的。),即转到“否”分支,即这里指向全局变量window,所以this.x实际上就是window . x;
让我们看一个调用构造函数的例子:
函数Point(x,y){ this . x=x;//这个?this.y=y//这个?} var np=new Point(1,1);np.x//1 var p=Point(2,2);p.x//错误,p是空对象未定义的window.x//2 var NP中的Point(1,1)函数=new Point(1,1)这在JavaScript this决策树’中判断如下:
1)var np=new Point(1,1)用new调用?这显然是,进入“是”分支,即这指向NP;
2)那么这个. x=1,也就是NP。x=1;
“JavaScript这个决策树”中var p=Point(2,2)中的Point(2,2)函数判断这个的过程如下:
1)var p=Point(2,2)是用new来调用的吗?这显然不是。转到“否”分支,即函数是否用点()调用。)?
2)2)点(2,2)函数不是用点()调用的。)?如果判断为否,则进入“否”分支,即此处指向全局变量window,所以this.x实际上就是window . x;
3)this.x=2表示window.x=2。
最后,让我们看一下用call和apply调用函数的例子:
函数Point(x,y){ this . x=x;this.y=ythis.moveTo=函数(x,y){ this . x=x;this.y=y} } var p1=new Point(0,0);var p2={x: 0,y : 0 };p1.moveTo.apply(p2,[10,10]);//apply实际上是p2.moveto (10,10) p2.x//10p1.moveto.apply (p2,[10,10])。在“JavaScript这个决策树”中判断的过程如下:
正如我们所知,apply和call方法非常强大,它们允许切换函数执行的上下文,也就是受其约束的对象。P1.moveTo.apply(p2,[10,10])实际上是p2.moveTo(10,10)。P2.moveTo(10,10)可以解释为:
1) p2。moveto (10,10)函数是否用new调用?这显然不是。转到“否”分支,即函数是否用点()调用。)?
2)函数p2.moveTo(10,10)用点()调用。),即转到“是”分支,即这里指向p2之前的对象p2。MoveTo (10,10),所以p2.x=10
关于JavaScript函数执行环境的过程,在IBM developerworks文档库中有一个描述感觉很好,摘录如下:
“JavaScript中的函数可以作为普通函数执行,也可以作为对象的方法执行,这也是这一点意义如此丰富的主要原因。当执行一个函数时,将创建一个ExecutionContext,函数的所有操作都将在这个执行上下文中发生。在构建这个执行环境时,JavaScript将首先创建参数变量,这些变量包含调用函数时传入的参数。接下来,创建范围链。然后初始化变量。首先初始化函数的参数表。该值是自变量变量中的相应值。如果参数变量中没有对应的值,则参数被初始化为未定义。如果函数包含内部函数,初始化这些内部函数。如果没有,继续初始化函数中定义的局部变量。需要注意的是,这些变量在此时被初始化为未定义,在成功创建ExecutionContext之前,不会执行赋值操作。这对我们理解JavaScript中变量的范围非常重要。鉴于篇幅,我们就不在这里第一次讨论这个话题了。最后,给这个变量赋值。如上所述,它将被分配给这个全局对象、当前对象等。根据不同的函数调用方法。此时,函数的ExecutionContext被成功创建,函数开始逐行执行,所有需要的变量都从之前构造的ExecutionContext中读取。”
理解这段文字对理解Javascript函数有很大的帮助。
以上是JavaScript中对这个关键词的详细介绍。一般来说,图片比文字更容易让大家理解。希望这篇文章对大家的学习有所帮助。