[Javascript实验课] What is this?

javascript 中的关键词 this 代指 执行上下文(Execution Contexts),函数做用域中的this,理解上来讲是指调用这个函数的对象。相信如下几个实验能够加深对this关键字的理解。javascript

实验一:全局下的this

全局做用域下的函数里面的this,显然等于全局对象windowhtml

function test(){
  console.log(this === window) //true
}
test()

因此,显然,能够经过this,改变window里面的全局变量java

var global = "global"

function test(){

  this.global = "global2"

}
test()
console.log(global)//global2

因此,若是你建立了一个构造函数,而后不当心调用了它,那么至关于你为全局对象赋值了,这个缺陷能够经过ES5里面的"use strict"来解决。闭包

"use strict";

var global = "global"

function test(){
  console.log(this)//undefined
  this.global = "global2"//TypeError because 'this' undefined

}
test();

严格模式下,全局模式下的函数内部的this为undefined,而不会默认为windowapp

实验二 : 对象中的this

经过普通对象声明的函数this函数

var myobject = {
  foo : function(){
    console.dir(this) //myobject
  }
}
myobject.foo()

foo里面的this指向调用foo的对象myobject,这个对象里面只有一个方法foo,所以咱们能够经过this操做 指向对象 里的其余值oop

var myobject = {
  v : 5,
  foo :  function(){
        this.v ++
        console.log(this.v)//6
   } 
}

myobject.foo()

多层对象的状况下,this指向最近的一个对象,即谁直接调用这个函数,谁是thisthis

var myobject = {
  foo : {
    bar : function(){
        console.dir(this)//foo
    }
  }

}
myobject.foo.bar()

以上状况this指向foo对象,那么咱们再考虑以下的状况code

var myobject = {
  foo : function(){
    console.dir(this)//myobject
    var bar = function(){
      console.dir(this)/*window "use strict" undefined*/
    }
    bar()
  }
}
myobject.foo()

咱们能够发现,若是在foo函数里声明新的函数(闭包),好比绑定事件,settimeout里的匿名函数等状况,这里面的this会变为window(严格模式下undefined)。
形成这个错误的缘由是,bar()调用的时候,是全局对象window在调用的它,而不是经过myobject调用(换句话说myobject里面压根就没有bar),这种状况下若是要经过myobject调用bar须要用到call或applyhtm

var myobject = {
  foo : function(){
    console.log(this)//myobject
    var bar = function(){
      console.log(this)
    }   

    bar.call(myobject)//myobject
  }

}
myobject.foo()

理解为,函数中的this,跟调用时的情形有关。

构造函数经过new来赋值情形也跟对象相似,好比

function testobject(){
  this.kk = 6;
  this.dd = function(){console.log(this)};
}

var fish = new testobject
fish.dd();

/*
[object Object] {
  dd: function (){window.runnerWindow.proxyConsole.log(this)},
  kk: 6
}
*/

new操做符会将this指向构造函数构造出来的对象

实验三:事件回调里的this

var myobject = {
  foo : function(){
    console.log(this)//myobject

    document.body.onclick = function(){
      console.dir(this)//[object HTMLBodyElement]
    }
  }
}
myobject.foo()

点击回调里的this指向点击对象

总结:解决办法

为避免this混乱,能够采用下面几种方法

经过变量传递

var myobject = {
  foo : function(){
    var that = this   
    document.body.onclick = function(){
      console.dir(that)//myobject
    }
  }
}
myobject.foo()

经过call或apply

var myobject = {
  foo : function(){
    var bar = function(){
      console.log(this)
    }   

    bar.call(myobject)//myobject
  }

}
myobject.foo()

直接用对象名代替this

var myobject = {
  v : 5,
  foo : function(){
    var bar = function(){
      console.log(++myobject.v)//直接修改myobject对象里的值
    }   
    bar();
  }

}
myobject.foo()

更多相关请参考

http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html

http://javascript.ruanyifeng.com/oop/basic.html

https://developer.mozilla.org/zh-CN/docs/JavaScript/Reference/Operators/this#Function_context_.E5.87.BD.E6.95.B0.E4.B8.8A.E4.B8.8B.E6.96.87

http://ryanmorr.com/understanding-scope-and-context-in-javascript/

http://stackoverflow.com/questions/9468055/what-does-new-in-javascript-do-anyway

相关文章
相关标签/搜索