一开始看到this
这个单词..这个关键字的时候,我一直都把他当成英语里面的这个————即window或者调用这个的函数,后面问过一些学JAVA的人。也没怎么弄懂。今天特地翻了下资料。在此总结下。
到底啥是this
对于this变量最要的是能够理清this所引用的对象到底是哪一个,也许很多资料上都有自己的解释,但有些概念讲的偏繁杂。而我的理解是:首先分析this所在的函数是当做哪个对象的方法调用的,则该对象就是this所引用的对象总体原则就是:是谁调用的,this 就指向谁
this调用的一般几种情况
- 全局调用
- 作为对象的方法调用
- 绑定事件调用
####当作为全局调用的情况
这么说吧 记住这一点全局变量都是window对象的属性这个时候this 一般指的就是window
比如这个例子1
2
3
4
5function arr (){
alert(this.name)
}
name="Z-one"
arr();
记住这一点全局变量都是window对象的属性一般单独调用的时候就是指向的全局window。
当作为对象的方法调用情况
还是来看这个例子1
2
3
4
5
6
7
8
9var x="Z-one";
var obj={};
obj.x="Acorn";
obj.y=function (){
alert(this.x)
}
var b=obj.y;
obj.y();
b();
结果很明显了
- 第一个obj,y() 是作为一个对象的方法调用的,这时候this 就自然而然的指向了这个对象.
- 而第二个b()为什么会输出”Z-one”呢,因为这里var b=obj.y我的理解是相当于做了一个赋值,但是运行b() 的时候还是把b()当成一个单独调用的形式(全局变量的方式调用),就好比有100块放在银行里,我现在手里有个同样的100块,怎么说这100块也不可能是银行的啊。还是我的。
作为绑定事件调用的时候,
这个就更好理解了。1
2
3$("li").on("click",function(){
console.log(this.html());
})
这个时候this 就是指向的绑定事件的目标”li”
还有个比较特殊的一个setTimeout的时候
当被定时器调用的时候 情况又比较特殊。我们来看下面这个例子1
2
3
4
5
6
7
8
9
10
11
12
13name="Z-one";
var obj={
name:"Acorn",
x:function(){
alert(this.name)
setTimeout(function(){
alert(this.name)
},1000)
}
}
var c=obj.x;
obj.x();
c();
结果已经很明显了。
- 第一个是属于当初一个对象的属性调用,this指向的是这个对象,this.name理所当然就是”Acorn”了,
- 然后执行c()。这里是属于一个全局调用的情况。this指向window。
- 然后就是两次定时器,这里记住一点。定时器也是指向的window.也就理所当然的是”Z-one”
在被作为对象的一个方法调用时候,在方法函数内部定义的函数(也就是函数中又存在一个函数)这时候this又有说不同
具体还是来看这个例子:1
2
3
4
5
6
7
8
9var obj={
x:function(){
function abc(){
alert(this.name)
}()
},
name:"Z-one"
}
var name ="xxx"
当运行的时候. abc是这个自执行函数,这时候this 指向了全局.
现在就很明确了:
- 当作为一个独立的函数调用(全局变量)的时候,根据是否是严格模式,this指向undefined或者window.
- 当作为对象的方法调用时候,this 指向调用的对象
- setTimeout这类的定时器,this 还是会指向window
如何改变this的指向呢?
还是上面那个例子,我如果想在函数内的二级函数内正常访问到我们想指的那个this 应该怎么办呢??
这里有两者方法
在一开始的时候,就是一级函数的时候,这时候this
还是指向的我们想要的this。这时候我们就把这个this
存起来
直接看代码1
2
3
4
5
6
7
8
9
10var obj={
x:function(){
var that=this;//这时候先把this存起来
(function abc(){
alert(that.name)
})()
},
name:"Z-one"
}
var name ="xxx"
这像这样
利用call和apply 来改变this的指向,让其指向我们指向的执行上下文(通过改变this内部的指针)
1 | function abc(){ |
这样结果就很明显了。
call 和apply的区别
call 和apply的作用都是改变对象的执行上下文。简而言之就是改变对象的内部指针,即改变对象的this指向内容。
一般的调用是“对象调用函数”,但call aply 是“函数调用对象”。
call 和apply的区别在于
- call传入的是具体的值
- apply传入的是一个数组
this的一些题目
下面代码输入什么1
2
3
4
5
6
7
8
9
10
11
12
13var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()
//输出 "jojn:hi!"
//这时候 调用方式是以一个对象的方法来调用,this指向的是这个对象
下面代码输出什么,为什么1
2
3
4
5
6
7
8
9
10func()
function func() {
alert(this)
}
//这里 因为函数提升,func()是可以运行的
输出 window
这里 调用方式是作为独立的函数调用,this 指向window
下面代码输出什么1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22function fn0(){
function fn(){
console.log(this);
}
fn();
}
fn0();
//这里的调用方式属于 在一个函数内部调用了一个二级函数.这时候this 指向的是全局(非严格模式)或者undefeined(严格模式)
document.addEventListener('click', function(e){
console.log(this);
setTimeout(function(){
console.log(this);
}, 200);
}, false);
// 这里是作为绑定事件来调用.this 当然指的就是被绑定的元素.
第一个指向 document
第二个是 定时器比较特殊,指向的是全局window
下面代码输出什么1
2
3
4
5
6
7
8
9
10var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john)
//输出 "john"
使用call改变了this的指向,让this指向了john这个函数.
下面代码输出什么1
2
3
4
5
6
7
8
9
10
11var john = {
firstName: "John",
surname: "Smith"
}
function func(a, b) {
alert( this[a] + ' ' + this[b] )
}
func.call(john, 'firstName', 'surname')
//输出 'john Smith'
使用call改变了函数func中this的指向,另外传入的参数是firstName 和Surname
下面代码有什么问题,如何修改?1
2
3
4
5
6
7
8
9
10
11
12var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么
this.showMsg();
})
},
showMsg: function(){
console.log('饥人谷');
}
}
这里是当做一个绑定事件在调用,此时的this 指向的是$btn.
当点击$btn的时候,会在控制台输出这个$btn节点。并且会报错。显示showMsg()is not undefined
修改如下1
2
3
4
5
6
7
8
9
10
11
12
13var module= {
bind: function(){
that=this;//这里的this 还是指向的是这个对象。
$btn.on('click', function(){
console.log(this)
that.showMsg();
})
},
showMsg: function(){
console.log('饥人谷');
}
}
下面代码输出什么1
2
3
4
5
6
7
8
9
10
11obj = {
go: function() { alert(this) }
}
obj.go(); //此时是调用方式是,当一个对象的方法调用,this 指向是这个对象本身.输出 object Object
(obj.go)(); //这里还是当成一个对象的方法调用,只是是一个自执行函数? 输出object window
(a = obj.go)(); //这里相当于给a添加一个指针,指向obj.go 这个函数,然后自执行这个a 这个函数(a是全局变量),此时this 指向的是window.
(0 || obj.go)();//这里0一直是false,运算后会得到(obj.go)这么一个匿名函数,这个函数时存在于window层面,运行这个函数的时候,this指向的就是window
如果是(0 || obj.go()) 这时候 this 指向的就是obj