一般涉及到这个问题,大部分的博客都说是谁调用的函数,this就指向谁,但是对于刚入门的人来说还是不太容易理解,像我当时就花了很久。。。可能是因为菜吧。
下面来讲一下我的理解
其实谁调用函数this指向谁的确是对的,但是如果基础不够好,是很容易判断错谁调用的函数
分类写比较好排版,所以分成了大概四类:
1.一般函数方法调用
//1.函数声明
var name = '张三'
function obj(){
var a = 'obj'
console.log(this)//window
console.log(this.name)//张三
}
obj()//window 张三
window.obj()//window 张三
1.为什么执行了obj()输出的是window?
因为obj是全局函数,是通过window直接调用的,所以执行obj()其实等同于执行window.obj(),所以其实就是window调用的obj,所以this指向window
函数表达式其实也是一样的:
//2.函数表达式
var name = '张三'
var obj = function(){
var a = 'obj'
console.log(this)//window
console.log(this.name)//张三
}
obj()//window 张三
window.obj()//window 张三
这是直接调用函数的情况,但是如果函数作为对象的属性去调用就有其他的情况了
2.作为对象的属性方法调用
//3.函数作为对象的属性去调用--例一
var a='window';
var obj={
name:"张三",
age:"20",
say:function(){
var a='obj';
console.log(this);//就是obj这个对象
console.log(this.a);//undefined
console.log(this.name);//张三
}
}
obj.say();//obj{} undefined 张三
window.obj.say(); //obj{} undefined 张三
1.为什么obj.say()中的this.a是undefined呢?
因为obj.say()中的say()执行的时候是obj直接调用的,因此this指向obj,所以虽然的确是window调用的obj,但是并不是window直接调用的say(),函数的this指向的是直接调用对象,这里是obj
我们继续看
//4.函数作为对象的属性去调用--例二
var a='window';
var obj={
name:"张三",
age:"20",
say:function(){
var a='obj';
console.log(this);//是obj这个对象
console.log(this.a);//undefined
console.log(this.name);//张三
}
action:{
name:"李四",
age:"25",
say:function(){
var a='obj';
console.log(this);//是action这个对象
console.log(this.a);//undefined
console.log(this.name);//李四
}
}
}
obj.say();//obj{} undefined 张三
obj.action.say();//action{} undefined 李四
window.obj.say(); //obj{} undefined 张三
window.obj.action.say();//action{} undefined 李四
1.为什么obj.action.say()执行结果和obj.say()不一样?
因为obj.action.say()执行say()的时候,其直接调用对象是action而不是obj,所以this指向的是action
然后我们来看另外一种情况
//5.函数作为对象的属性去调用--例三
var a='window';
var obj={
name:"张三",
age:"20",
say:function(){
var a='obj';
console.log(this);//就是obj这个对象
console.log(this.a);//undefined
console.log(this.name);//张三
function action(){
console.log(this);//window
console.log(this.a);//window
console.log(this.name);//(空)
console.log(this.age);//undefined
}
action();
}
}
obj.say();
window.obj.say();
1.为什么执行action()的时候this指向window?
因为action()只是在say()函数中进行了普通调用,并不是obj或者say直接调用,所以这时候指向的是全局对象window,
2.为什么this.name为空而this.age是undefined?
因为window全局对象本身就有一个默认为空的字段name,所以name是空。
3.怎么让action指向obj
在say中用一个变量保存this就然后action()中使用该变量即可。例如在say()函数中var that = this,然后action()函数中把this全部替换为that,就会达到我们想要的效果了。当然还可以使用call或者apply,有关call和apply可以看我的博客
3.作为构造函数调用
var name = 'window'
function obj(){
this.name = 'obj'
var age = 20
console.log(this)//a:obj{} b:window
console.log(this.name)//a:obj b:obj
console.log(this.age)//undefined
}
var a = new obj()
var b = obj()
console.log(name)//obj
关于new可看我的博客 —— js new一个函数和直接调用函数的区别
var name = 'window'
function obj(){
var age = 20
this.name = 'obj';
console.log(this)
console.log(this.name)
console.log(age)
// this.aa = function(){
// return this.name
// }
}
var a = new obj()
var b = obj()
console.log(name)
1.a和b声明的时候发什么了什么?
声明a的时候使用了new,新建了一个对象a,然后obj()中的this指向a,a再链接obj的原型链,再执行obj(),所以a执行时直接调用对象是a
b其实只是window对象执行了obj()然后将返回值赋给b,如果没有返回值那么b为undefined
1.为什么b中this.name也是obj呢?
因为执行obj()的时候this指向的是window,所以在执行this.name='obj'等同于window.name='obj',所以声明b之后输出name也是obj
4.箭头函数
箭头函数中根本没有自己的this,因此this指向的是父执行上下文(简单对象(非函数)没有执行上下文)
有关于执行上下文可看 —— 执行上下文的原理及使用
5.构造函数
构造函数可以看js new
new的时候会新建一个空间并连上构造函数的原型链,再把构造函数的this指向实例,所以调用的属性和方法中的this都是指向实例
Person(){
this.name=name
this.age=age
this.show=function(){
console.log(this.name)
console.log(this.age)
}
}
var a = new Person('张三',20)
a.name//张三
a.age//20
a.show()//张三 20