Javascript是一门基于对象的动态语言,也就是说,所有东西都是对象,一个很典型的例子就是函数也被视为普通的对象。Javascript可以通过一定的设计模式来实现面向对象的编程,其中this指针就是实现面向对象的一个很重要的特性。

Javascript的this指针一个十分简略了解错,然后用错的特性。特别是关于触摸静态言语比较久了的同志来说更是如此。

示例阐明

咱们先来看一个最简略的Javascript this指针示例:

这段代码很简略,咱们界说了一个大局字符串目标name和函数目标sayHi。运转会弹出一个打招待的对话框,“你好,我的名字叫Kevin Yang”。

咱们把这段代码略微改一改:

这段代码和上段代码的差异就在于sayHi函数在运用name的时分加上了this.前缀。运转成果和上面一摸相同。这阐明this.name引证的也仍是大局的name目标。

最初咱们不是说了,函数也是一般的目标,能够将其当作一个一般变量运用。咱们再把上面的代码改一改:

这一次,咱们又创立了一个大局目标person,并将sayHi函数目标赋给person目标的sayHello特点。运转成果如下:

谈谈Javascript的this指针(javascript this指针)  Javascript this指针 第1张

这一次打招待的内容就有点无厘头了,咱们发现this.name现已变成undefined了。这阐明,在sayHello函数内部履行时现已找不着this.name目标了。假如咱们从头界说person目标,在其上面加上一个name特点又会怎么样呢?

var person = {name:"Marry"};运转代码发现打招待的“人”变了:

是不是看出点道道了呢?

判别Javascript的this指针辅导性准则

在Javascript里边,this指针代表的是履行当时代码的目标的一切者。

在上面的示例中咱们能够看到,***次,咱们界说了一个大局函数目标sayHi并履行了这个函数,函数内部运用了this关键字,那么履行this这行代码的目标是sayHi(全部皆目标的表现),sayHi是被界说在大局效果域中。其实在Javascript中所谓的大局目标,无非是界说在window这个根目标下的一个特点罢了。因而,sayHi的一切者是window目标。也便是说,在大局效果域下,你能够经过直接运用name去引证这个目标,你也能够经过window.name去引证同一个目标。因而this.name就能够翻译为window.name了。

再来看第二个this的示例。咱们界说了一个person的目标,并界说了它的sayHello特点,使其指向sayHi大局目标。那么这个时分,当咱们运转person.sayHello的时分,this地点的代码所属目标便是sayHello了(其实精确来说,sayHi和sayHello是只不过相似两个指针,指向的目标实际上是同一个),而sayHello目标的一切者便是person了。***次,person里边没有name特点,因而弹出的对话框便是this.name引证的便是undefined目标(Javascript中一切只声明而没有界说的变量全都指向undefined目标);而第2次咱们在界说person的时分加了name特点了,那么this.name指向的天然便是咱们界说的字符串了。

了解了上面所说的之后,咱们将上面***一段示例改构成面向目标式的代码。

在上面这段代码中,咱们界说了一个Person的“类”(实际上仍是一个目标),然后在这个类的原型(类原型相当于C++中的静态成员变量的概念)中界说了sayHello特点,使其指向大局的sayHi目标。运转代码咱们能够看到,marry和kevin都成功的向咱们打了声“招待”。

在这段代码中有两点需求考虑的,一个是new咱们很熟悉,但是在这儿new究竟做了什么操作呢?别的一个是,这儿履行sayHello的时分,this指针为什么能够正确的指向marry和kevin目标呢?

咱们来把上面界说“类”和实例化类目标的操作从头“翻译”一下:

当然这段代码并不能正确履行,但是它能够协助你更好的了解这个进程。

当咱们运用new关键字实例化一个“类”目标的时分,Javascript引擎会在这个目标内部界说一个新的目标并将其存入this指针。一切此目标内部用到this的代码实际上都是指向这个新的目标。如this.name = name,实际上是将参数中的name目标赋值给了这个新创立的目标。函数目标履行完之后Javascript引擎会将此目标回来给你,所以就有marry变量得到的目标的name为“Marry”,而kevin变量得到的目标的name特点的确“Kevin”。

简略误用的状况

了解了this指针后,咱们再来看看一些很简略误用this指针的状况。

示例1——内联式绑定Dom元素的事情处理函数

  1. "btnTest"type="button"value="点击我"onclick="sayHi()">

在此例代码中,咱们绑定了button的点击事情,希望在弹出的对话框中打印出点击元素的标签名。但运转成果却是:

也便是this指针并不是指向input元素。这是由于当运用内联式绑定Dom元素的事情处理函数时,实际上相当于履行了以下代码:

在这种状况下sayHi函数目标的一切权并没有产生搬运,仍是归于window一切。用上面的辅导准则一套咱们就很好了解为什么this.tagName是undefined了。

那么假如咱们要引证元素自身怎么办呢?

咱们知道,onclick函数是归于btnTest元素的,那么在此函数内部,this指针正是指向此Dom目标,所以咱们只需求把this作为参数传入sayHi即可。

  1. "btnTest"type="button"value="点击我"onclick="sayHi(this)">等价代码如下:

示例2——暂时变量导致的this指针丢掉

咱们在写略微有点规划的Js库的时分,一般都会自己封装一个Utility的类,然后将一些常用的函数作为Utility类的特点,如客户端常常会用到的getCookie函数和解码函数。假如每个函数都是互相独立的,那么还好办,问题是,函数之间有时分会彼此引证。例如上面的getCookie函数,会对从document.cookie中提取到的字符串进行decode之后再回来。假如咱们经过Utility.getCookie去调用的话,那么没有问题,咱们知道,getCookie内部的this指针指向的仍是Utility目标,而Utility目标时包括decode特点的。代码能够成功履行。

但是有个人不小心这样运用Utility目标呢?

这个时分运转代码会抛出反常“this.decode is not a function”。运用上面咱们讲到的辅导准则,很好了解,由于此刻Utility.getCookie目标被赋给了暂时变量getCookie,而暂时变量是归于window目标的——只不过外界不能直接引证,只对Javascript引擎可见——所以在getCookie函数内部的this指针指向的便是window目标了,而window目标没有界说一个decode的函数目标,因而就会抛出这样的反常来。

这个问题是由于引进了暂时变量导致的this指针的搬运。处理此问题的办法有几个:

不引进暂时变量,每次运用均运用Utility.getCookie进行调用getCookie函数内部运用Utility.decode显式引证decode目标而不经过this指针隐式引证(假如Utility是一个实例化的目标,也便是经过new生成的,那么此法不可用)

运用Funtion.apply或许Function.call函数指定this指针

前面两种都比较好了解,第三种需求提一下。正是由于this指针的指向很简略被搬运丢掉,因而Javascript供给了两个相似的函数apply和call来答应函数在调用时从头显式的指定this指针。

批改代码如下:

call和apply只要语法上的差异,没有功能上的不同。

示例3——函数传参时导致的this指针丢掉

咱们先来看一段问题代码:

这段代码希望在访客进入页面5秒钟之后向访客打声招待。setTimeout函数接纳一个函数作为参数,并在指定的触发时间履行这个函数。但是,当咱们等了5秒钟之后,弹出的对话框显现的this.name却是undefined。

其实这个问题和上一个示例中的问题是相似的,都是由于暂时变量而导致的问题。当咱们履行函数的时分,假如函数带有参数,那么这个时分Javascript引擎会创立一个暂时变量,并将传入的参数仿制(留意,Javascript里边都是值传递的,没有引证传递的概念)给此暂时变量。也便是说,整个进程就跟上面咱们界说了一个getCookie的暂时变量,再将Utility.getCookie赋值给这个暂时变量相同。只不过在这个示例中,简略忽视暂时变量导致的bug。

函数目标传参
关于函数作为参数传递导致的this指针丢掉的问题,现在许多结构都现已有办法处理了。

Prototype的处理计划——传参之前运用bind办法将函数封装起来,并回来封装后的目标

bind办法的完成其实是用到了Javascript又一个高档特性——闭包。咱们来看一下源代码:

3

首先将Javascript的this指针存入函数内部暂时变量,然后在回来的函数目标中引证此暂时变量然后构成闭包。

微软的Ajax库供给的计划——构建托付目标

其实本质上和prototype的方法是相同的。

闻名的Extjs库的处理计划选用的方法和微软是相同的。

【修改引荐】

  1. JavaScript类和承继:prototype特点
  2. JavaScript类和承继:this特点
  3. ExtJS Grid Tooltip的3+1种完成方法总结
  4. JavaScript异步调用结构的链式完成
  5. JavaScript异步调用结构的jQuery风格链式调用
转载请说明出处
知优网 » 谈谈Javascript的this指针(javascript this指针)

发表评论

您需要后才能发表评论