你的位置:首页 > Java教程

[Java教程]javascript中让你捉摸不定的this


this到底指向谁,估计很多人在使用javascript的过程中都遇到过,这个关键字如果没搞懂,在一些高级功能中都会困难重重,搜了下相关文章,介绍的都挺多的,也有很深入的,比如汤姆大叔的《深入理解javascript系列》文章。看到很多文章中提到一句话:"this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁实际上this的最终指向的是那个调用它的对象"。

《javascript设计模式与实践》中是这样说的:javascript的this总是指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境

除去不常用的with和eval,实际应用中,this的指向大致分为下面4种情况:

1、作为对象的方法调用。

2、作为普通函数调用。

3、构造器函数调用。

4、call和apply调用。

情况1:作为对象的方法调用

当函数作为对象的方法调用时,this指向该对象。这是最常见的,比如:

var obj={ a:1, fun:function(){  console.log(this.a);//输出:1 }};obj.fun();

情况2:作为普通函数调用

当函数不作为对象的属性调用时,即作为普通函数调用,this总是指向全局对象。

var a=1;function fun(){ var a=2; console.log(this.a);//输出:1
 console.log(a);//输出:2}fun();

再看一种情况:

var name="张三";var obj={ name:"李四", getName:function(){  console.log(this.name); }}obj.getName();//输出:李四var getName=obj.getName;getName();//输出:张三

 直接调用obj.getName(),这里的this是作为对象的方法调用,所以它指向obj,this.name就是李四;

obj.getName赋值给getName后,getName就变成了普通函数,所以指向的是全局的window.name,结果是张三;

举个在实际开发过程中遇到的会让人困惑的例子:

<!DOCTYPE html><html><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>JS Bin</title></head><body> <button id="btn">点我</button> <script type="text/javascript">  var id="window";  document.getElementById("btn").onclick=function(){   alert(this.id);//输出:btn   var callback=function(){    alert(this.id);//输出:window   }   callback();  } </script></body></html>

  点击按钮的时候this指向的是按钮,但是callback是作为普通函数调用的,里面的this指向的是全局对象window,所以结果是window。

此时我们可以临时用一个变量保存对当前对象的引用:

var id="window";  document.getElementById("btn").onclick=function(){   var self=this;   var callback=function(){    alert(self.id);//输出:btn   }   callback();  }

情况3:构造器中调用

function myClass(){ this.name="张三";}var child=new myClass();console.log(child.name);//输出:张三

大部分的javascript函数都可以当做构造函数来使用,构造器函数外表跟普通函数一模一样,区别在于调用的方式。当使用new运算符调用函数时,该函数总会返回一个对象,就是我们常说的实例对象。通常情况下,通过new运算符后,构造器函数中的this就指向的实例对象。

注意:如果构造器函数显式的返回了一个object类型的休息,那么运算结果最终会返回这个对象,而不是上面所期望的。例如:

function myClass(){ this.name="张三"; return {  name:"李四" }}var child=new myClass();console.log(child.name);//输出:"李四"console.log(child);//输出:[object Object] {name: "李四"}

  

 这个例子与上面的例子差别就在于构造器函数最后返回了一个对象。如果构造器函数不显式的返回任何数据,或者返回一个非对象类型的数据,就不会出现这种情况,例如:

function myClass(){ this.name="张三"; return "李四"}var child=new myClass();console.log(child.name);//输出:张三console.log(child);//输出:[object Object] {name: "张三"}

情况4:call和apply

call和apply能够动态的修改传入函数的this:

var obj1={ name:"张三", getName:function(){  console.log(this.name); }};var obj2={ name:"李四"};obj1.getName();//输出:"张三"obj1.getName.call(obj2);//输出:"李四"obj1.getName.apply(obj2);//输出:"李四"

  

call和apply的作用这里就不详细说了。

 




青海旅游住哪里比较方便青海旅游住宿攻略青海旅游最佳时间青海自驾游最佳路线青海旅游多少钱海螺沟:雪花飘零 轻轻地我走了 甘孜州明显区别与其他藏族地区的禁忌风俗 出境人文风俗:苗族花带心灵手巧的苗家姑娘之绣 海螺沟:原始冰川 别样美丽 萃溪江漂流小孩能玩吗?诸暨萃溪江漂流有年龄限制吗? 济南到潍坊富华游乐园怎么走?济南到富华游乐园乘车路线? 萃溪江漂流门票2015-5-7月诸暨萃溪江漂流门票价格 潍坊火车站到富华游乐园和金宝游乐园哪个近些?潍坊富华游乐园和金宝乐园哪个好? 中山西区富华道怎么去金钟水库??要多久?_山西旅游攻略 十一国庆长假自驾车旅游推荐 玄真漂流在哪?玄真漂流价格是多少? 英德有哪些地方好玩?要收门票吗?多少钱? 最美黄金海岸 白浪逐沙滩(全文) 十一黄金周去哪玩,出境游要注意什么? 龙女沟有什么好玩的?融水龙女沟景区门票包括哪些? 横琴口岸通关时间是什么时候?怎么去? AT28C256-15/25/20DC Datasheet AT28C256-15/25/20DC Datasheet AT28C256-15/25D Datasheet AT28C256-15/25D Datasheet AT28C256-15/25DI Datasheet AT28C256-15/25DI Datasheet 迪拜是一个国家吗 迪拜是一个国家吗 迪拜是一个国家吗 深圳西冲小木屋 深圳西冲小木屋 深圳西冲小木屋 佛冈森波拉 佛冈森波拉 佛冈森波拉