彻底搞懂js this指向问题
在这里必须要提一句的是,this指向是学习js必须要掌握的(必须),再开始之前先看底部的总结,然后回上面看例子便一目了然。
例子1:
function a(){ var user = "TangSir"; console.log(this.user); //undefined console.log(this); //Window } a();
看总结第2条,这里函数本身没有被父级对象调用,那么这里就指向window
function a(){ var user = "TangSir"; console.log(this.user); //undefined console.log(this); //Window } window.a();
可以发现是一样的,这是因为window是全局对象,这里的a是被window点出来的,所以指向window(在这里也可以把window理解为a的父级,那么就是总结第3条)
例子2:
var o = { user:"TangSir", fn:function(){ console.log(this.user); //TangSir } } o.fn();
这里的this指向o(总结第3条)
var o = { user:"TangSir", fn:function(){ console.log(this.user); //TangSir } } window.o.fn();
这里加了个window,但是fn的父级还是o,是o调用了它(总结第3条)
var o = { a:12, b:{ a:14, fn:function(){ console.log(this.a); //14 } } } o.b.fn();
这里父级是b,那么this指向b(总结第3条)
例子3:
var o = { a:12, b:{ a:14, fn:function(){ console.log(this.a); //undefined console.log(this); //window } } } var j = o.b.fn; j();
这里为何是undefined而不是14?是谁最后调用了它,这里是j(),那么this只能是window(总结第1条)
例子4:
function Fn(){ this.user = "TangSir"; } var a = new Fn(); console.log(a.user); //TangSir
构造函数的this指向函数实例本身,这里赋给了a,等于赋值了一份给了a,那么a.user肯定也是TangSir(总结第5条)
例子5:
function Fn() { this.user = 'TangSir'; return {}; } var a = new Fn(); console.log(a.user); //undefined
因为返回的是对象,所以this指向该对象,所有是undefined(总结第6条)
function Fn() { this.user = 'TangSir'; return function(){}; } var a = new Fn(); console.log(a.user); //undefined
function同样是对象,所以this指向该对象,所有是undefined(总结第6条)
function Fn() { this.user = 'TangSir'; return 1; } var a = new Fn(); console.log(a.user); //TangSir
这里this指向函数实例本身,所以是TangSir(总结第6条)
function Fn() { this.user = 'TangSir'; return undefined; } var a = new Fn(); console.log(a.user); //TangSir
这里this指向函数实例本身,所以是TangSir(总结第6条)
function Fn() { this.user = 'TangSir'; return null; } var a = new Fn(); console.log(a.user); //TangSir
函数里有null比较特殊,这里this指向函数实例本身,所以是TangSir(总结第6条)
例子6:
var obj = { name:"TangSir", fn:function(){
fn1=()=>{
console.log(this.name); //TangSir }
fn1(); } } obj.fn();
这里箭头函数父级是fn,去掉父级后,fn1()此时的父级就是obj,那么this.name自然是TangSir(总结第6条和第3条)
例子7:
var o = { a:12, b:{ a:14, c:{
a:15,
d:function(){
console.log(this.a); //15
function e(){
console.log(this.a); //undefined
f();
}
e();
function f(){
console.log(this.a); //undefined
}
g=()=>{
console.log(this.a); //15
}
g();
}
} } } o.b.c.d();
这里第一个console是15(总结4),第二和第三个console是undefined,不然理解,它们的调用时f()和e(),所以是undefined,第三个是箭头函数,根据例子6结合总结第7条,得出15
总结:
1、this在函数定义的时候是没办法确定指向的,只有函数执行的时候,最后谁调用了它才能确定this指向谁
2、如果函数中有this,但是函数本身没有被父级(上一级)对象调用,那么就指向window
3、如果函数中有this,且函数本身被父级(上一级)对象调用,那么this就指向上一级对象
4、如果函数中有this,且函数中有多个对象,尽管函数被最外层对象调用,但this仍然指向父级(上一级)对象
5、构造函数中this,指向构造函数实例,如果创建的实例赋给对象,那么等于复制了一份给对象,该对象也拥有实例中的this(new出来的构造函数可以改变this指向)
6、构造函数中带return,返回值若是对象,this指向的是那个返回的对象,返回值若是null,this还是指向那个构造函数实例
7、es6中=>箭头函数中的this,去掉当前函数的父级(上一级)对象,再看this指向谁,此时指向谁就是谁(结合第3条)