函数执行的时候,除了能看见的代码在执行,还有js自身的东西也在运行,其中就有运行的上下文,这个运行的上下文就是this本身。执行的上下文其实就是函数所处的对象。
当定义一个对象,对象里面有属性和方法,在这个对象里的方法this都指向这个对象。虽说this指向调用它的对象,但是最终能调用它的对象一般都是这个方法所处的对象。需要注意的是,这个方法所处的对象是它所处的第一级对象。
var o = {
okey1: '最外层key',
a: {
akey1: '内层对象',
function afun() {
console.log(this.okey1,this.akey1) // undefine, 内层对象
}
}
不过在浏览器环境,当直接定义一个function时,这个function会被挂载到window对象上,它的this直接指向window。其实不只是function会挂载到windo,变量也会被直接挂载到windwo。使用var 直接定义的变量,都会被默认挂载到window上,这也是为什么var变量会成为全局变量的原因,window对象只要存在,全局变量就存在。
简单来说,浏览器环境下,网页加载之后,先创建的一个window对象(每个标签页都有一个独立的window对象),我们的东西会被浏览器挂载到window对象里面(浏览器行为,因为js运行在浏览器内,调用系统资源的时候需要浏览器帮忙调用,window对象提供js调用系统资源)。在函数执行的时候,其实是执行window.functionName(),此时函数的调用者是window。当我们自己定义了一个对象的时候,对象内部的函数被调用的时候,是这样的关系(任然用上面的o对象举例):
o.a.afun()实际上是window.o.a.afun(),这个时候调用afun的其实是window.o.a这个对象,此时的this指向了window.o.a。
举一个this改变的列子(严格来说不叫this改变):
function foo() {
this.a = 3
}
var obj1 = {
a: 1
}
obj1.call(foo)
console.log(obj1.a) // 3
先说一下call()和apply()方法,我理解的call或者是apply()的实际作用,就是隐藏的在对象内部添加一个和需要call(或apply)一样的方法,添加完成后再执行它。
obj1.call(foo)就等价于下面的代码
obj1.foo = foo()
obj1.foo()
PS:在js里面,表达式会被处理成结果才继续下一步。
function foo() {
this.a = 3
}
var obj1 = {
a: 1
}
var bar = foo.bind(obj1)
var newBar = new bar()
此时的new bar() 等价于new {
a: 1,
foo: function() {
this.a = 3
}
}
可能有不对的地方还望指正。