JavaScript中this的解释

JavaScript中this的解释

在java中 this 指的是当前类的对象。而在js中其实this最根本的特性还是和OO(面向对象)语言中的定义相吻合的。This对象在执行时是基于函数的执行环境绑定的,当函数被作为某个对象的方法调用时,this就指向那个对象。当然js中的this还有一些特殊的特性和用法。

首先:所有 JavaScript 全局对象、函数以及变量均自动成为 window 对象的成员。全局变量是 window 对象的属性。全局函数是 window 对象的方法。 

总结:

this指代为谁的对象,要看如何去调用这个函数。从根本上说它还是指的是当前对象(当前对象的执行环境或者说这个方法属于谁)

当一个函数作为全局对象去调用的话,this均指向的是window对象[例如:window.test()一般window会省略,函数test中的this指的就是window对象]。

当一个函数作为对象的一个方法时,this指的就是当前对象。[例如:var obj={者里面的this指的就是当前对象obj}]。

当一个函数作为一个构造函数使用时,this这个时候指向的是函数构造出来的对象。[例如:var o = new obj();obj()函数中的this,值的是o这个对象]

另外在标签中事件触发时使用的this都指的是当前的标签(元素)对象,这里多数都会在带参函数中使用到。并且,定义在标签中的函数调用,会被解析成

标签对象.事件= function (event) {//...这里的this指的是event.currentTarget,也就是标签对象};

一、Js中this一般使用的情况

   (了解了这几种下this指向谁,你就明白this)   

    1. 纯函数(作为函数调用)
    2. 对象方法调用(作为方法调用)
    3. 使用new调用构造函数
    4. 内部函数
    5. 使用call / apply
    6.事件绑定

二、调试常用方法

     alert();可以查看是否进函数,是否执行了某函数。还可以弹出某个对象的取值。

     console.log(); console.info(String,Object);

    console.asser(boolean);//断言false断言失败错误,true控制台不会输出什么

    在控制台输出,可以开发者模式下,找到输出的内容。比alert表现更具体一点。

    火狐有个非常强大的调试插件:Firebug(在附加组件中搜索firebug下载启用)

三、详细分析代码

1、纯函数中的this         

var o = {prop:37};

var name = 'this is window';  //定义window的name属性

function getName(){

       console.log(this);//输出: Window-this指向的是全局对--window对象

       console.log(this.name);  //控制台输出: this is window        

}

getName();   

    运行结果分析:纯函数(全局函数)中的this均指向了全局对象,即window。因为这种调用方法,最原始的应该是:window.getName();但我们通常都会省略。调用它的对象是window。this指向当前调用它的对象,即window.
注:根据ECMAScript3和非严格的ECMAScript5对函数的调用的规定,this指代全局对象。然而在严格模式下则是undefined

2. 对象环境中    

var o = {prop:37};

var name = 'this is window';  //定义window的name属性      

var testObj = {

     name:'this is testObj',

     getName:function(){

     console.log(this);  //输出:testObj ---this指向的是testObj对象

     console.log(this.name); //控制台输出: this is testObj             

     }

}       

 testObj.getName();  

    运行结果分析:当函数作为对象的一个方法时,被调用方法中this均指向了调用该方法的这个对象。创建对象的方式:<1>var a={}表示声名了一个,不包含任何自定义的属性和方法的对象。<2> var a=new a(); 其实和var a={}是等价的。在这个案例中getName()函数被作为testObj对象的一个方法,其均指向调用它的对象。

var o = {prop:37};

o.f = independent;

console.log(o.f)     //37

o.b = {g:independent,prop:42};

console.log(o.b.g());  //42

function independent(){return this.prop;}

    当我们使用o对象去调用f()方法时,this指向的是当前调用它的对象o,所以this.prop输出的是o对象中的prop属性。而当我们给o对象再添加一个对象时,此时o.b被作为一个对象,去调用g()方法时,this.prop输出的是o.b对象中的prop属性值。

3.  使用new调用构造函数 

function getObj(){

      console.log(this); //输出: getObj{}-this指向的新创建的getObj对象

   }

      new getObj();       //实例化了指向新生对象

    运行结果分析:new 构造函数中的this指向新生成的对象。当我们使用new关键字实例化一个“类”对象的时候,Javascript引擎会在这个对象内部定义一个新的对象并将其存入this指针。所有此对象内部用到this的代码实际上都是指向这个新的对象。

例如更直观的:

function C(){ this.a = 37;}

var o = new C();

console.log(o.a);  //输出结果:37

4. 内部函数/内部嵌套函数

var name = "this is window";  //定义window的name属性,看this.name是否会调用到

 var testObj = {

     name : "this is testObj",

     getName:function(){

            var self = this;   //临时保存this对象

             var handle = function(){

            console.log(this); //输出:Window(this指向的是全局对象--window对象)

            console.log(this.name);  //输出: this is window   

            console.log(self);//这样可以获取到的this即指向testObj对象(对象拥有

                                   name属性和getName()方法)       

.           }

                handle();

            }  

      }

 testObj.getName();


    运行结果分析:内部函数中的this仍然指向的是全局对象window。在内部函数中的this没有按预想绑定到外层函数中,而是绑定到了全局对象。这里涉及到了闭包的应用。闭包会将其空间扩展到外层函数空间之外,止步于全局空间,这时闭包中的this就指的是window对象。但是没有人希望内部函数被绑定到全局对象上。Js为了规避这种错误,设计了可以使用临时对象保存外层函数的this var self= this是testObj 对象的一个方式,所以此时的self指的是testObj对象,被保存在起来了,在内部函数中去使用时是可以取得的。

若是把上面案例: handle();  ——— 改为  new  handle();

此时输出的结果:

console.log(this);//控制台输出:handle,因为使用了new实例化了handle构造函数

console.log(this.name);//控制台输出:undefined,因为handle对象中并没有name属性,所以会为undefined

console.log(self);//控制台输出:指向testObj对象

进一步验证了这个结论:this均指的是当前调用它的对象。

4.1换一种方式

var name="this is window";

 var newname = "hhd";

 function a(name){

      this.name = newname;

      function getname(){

          alert(name)

          console.log(this);      //输出的window

          console.log(this.name); // 输出的结果为this is window

      }
          console.log(this); //输出的结果object-->a

          getname();
  }

new a(name);   //a对象中的this,均指向的是当前对象,实例化了构造函数

4.2补充说明

(先了解==和===区别

var a = 3; 

var b = "3"; 

a==b 返回 true   //等于

a===b 返回 false  //严格等于会匹配类型和值)

var o={m:function(){

    var self=this;

    console.log(this===o); //true,对象方法调用,this指向调用该方法的对象

    f();  

    function f(){ //定义一个嵌套函数

          console.log(this===o); //false嵌套函数(内部函数)不会继承调用它的外函数的this

          console.log(self===o); //true

    }

}};

o.m();   

5. 使用call / apply

Javascript引擎不允许我们自己写代码来做这样的事情,也就是说,在Javascript中,你不可以直接写this = someObj这样的代码。Javascript引擎通过以下两种方式允许我们显式指定this指针指代的对象:使用call / apply的函数里面的this指向绑定的对象。

这两个方法的用途都是在特定的作用域中调用函数。call()和apply()的第一个参数用作this的对象(即设置函数体内this对象的值)。Call(设置this的对象,其他参数...)而apply(设置this的对象,数组或者arguments对象)。

例如:

  function sayColor(sPrefix,sSuffix) {

     alert(sPrefix + this.color + sSuffix);   //The color is blue a very nice color indeed.

   };

//若是直接看sayColor这个函数的话,这里的this就得看这个函数的调用方式来决定this指代的是谁。

  var obj = new Object();

  obj.color = "blue";

  sayColor.call(obj, "The color is ", " a very nice color indeed.");

//而我使用sayColor.call()去调用的话,指定了sayColor函数中的this指代的是obj这个对象,所以才会有“The color is blue a very nice color indeed.”

扩展:事件绑定

事件方法中的this应该是最容易让人产生疑惑的地方,大部分的出错都源于此。

 //页面Element上进行绑定

<script type="text/javascript">

  function btClick(){

      console.log(this); //控制台输出: Window --- this指向的是全局对象

  }

</script>

<body>

  <button id="btn" onclick="btClick()" >点击</button>

</body>

上面这段代码相当于:

  document.getElementById("btn").onclick = function(){

      btClick();

  }

  btClick函数的所有权被没有发生转移。

  //js中绑定方式(1)

<body>

  <button id="btn">点击</button>

</body>

<script type="text/javascript">

  function btClick(){

     console.log(this); //控制台输出:<button id="btn">点击</button> //this指向的是HTMLButtonElement按钮对象

  }

  document.getElementById("btn").onclick = btClick;

  document.getElementById("btn").onclick(); //默认点击

</script>

//创建了一个文档对象(HTMLButtonElement按钮对象)去调用了btClick()这个方法,此时的btClick方法被绑定为该元素对象的一个方法。所以这里面的this指的是该元素对象。  
       

 //js中绑定方式(2) 

<body>

  <button id="btn">点击</button>

  </body>

  <script type="text/javascript">

  document.getElementById("btn").onclick = function(){

  console.log(this); //控制台输出:<button id="btn">点击</button> //this指向的是Element按钮对象

  }

  document.getElementById("btn").onclick();

  </script><body>

  <button id="btn">点击</button>

  </body>

  <script type="text/javascript">

  document.getElementById("btn").onclick = function(){

  console.log(this); //控制台输出:<button id="btn">点击</button> //this指向的是Element按钮对象

  }

  document.getElementById("btn").onclick();

  </script>


    运行结果分析:以上2种常用事件绑定方法,在页面Element上的进行事件绑定(οnclick="btClick();"),this指向的是全局对象;而在js中进行绑定,除了attachEvent绑定的事件方法(this指向的是全局对象)外,this指向的是绑定事件的Elment元素。

7、参数上的应用

另外在参数上的用法,指的是当前的标签对象 this.id 这里指的是button的id属性 

<button id="a1" onclick="btClick(this.id)">点击</button> //弹出a1

  <button id="a2" onclick="btClick(this.id)">点击</button> //弹出a2

  <script type="text/javascript">

  function btClick(num){

  alert(num) ; //a1 / a2

  alert(this) ; //window

  }

  </script>

以上代码运行时会被解析为:

<script type="text/javascript">

document.getElementById("a1").onclick = function (event) {

  alert(event); //object MouseEvent

  alert(event.currentTarget); //object HTMLButtonElement

  alert(target); //object HTMLButtonElement

  alert(this); //object HTMLButtonElement

};

 </script>

例如:

<input id="myBtn" name="btnTest" type="button" value="点击我" >

 <script type="text/javascript">

var btn = document.getElementById("myBtn");

btn.onclick = function (event) {

  console.log(event.currentTarget); //[object HTMLInputElement]

  console.log(event.target); //[object HTMLInputElement]

  alert(event.currentTarget === this); //ture

  alert(event.target === this); //ture

};

 </script>
<input id="myBtn" name="btnTest" type="button" value="点击我" >

 <script type="text/javascript">

document.body.onclick = function (event) {

  alert(event.currentTarget === document.body); //ture

  alert(this === document.body); //ture

  alert(event.target === document.getElementById("myBtn")); //ture

};

 </script>

event.currentTarget //事件处理程序真正注册的元素(即冒泡或者捕获是真正走到元素目标)

event.target //是真正的鼠标点击的目标元素(到达真正目标)

练习:

var t =function(){

  this.a = "我是t";

  alert(this);

  setInterval(function(){

  alert(this.a);

  },1000);

  }

  new t();

第一个弹出:object Object //var t =function()这种写法实际会解析成:var t =new Function();

var function_name = new function(arg1, arg2, ..., argN, function_body)

第二个弹出:undefined //定时器他的所属环境是全局所以,定时器中的this代表的是window对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

穆瑾轩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值