JavaScript底层知识系列(二)关于This史上最详细的解读

js中的this是一个老生常谈的话题。这篇文章可能是对于this来讲最全面的解读了,仔细看。

1.首先,要明白js中对象的概念,我们说js的对象大致分为dom对象,bom对象,也就是说,html页面叫对象,浏览器算对象,js中自己建立的对象也叫对象。

实际上,我们在日常编程的过程中很可能没有建立对象,可能写代码的时候谢了n多个变量,写了n多个方法,程序也能正常运行。

于是你会说,我也没用对象啊?实际上,你写的所有的变量,方法都保存在window对象里。window是一个浏览器的全局对象,例如

var a=1;
console.log(a);//1
console.log(window.a);//1

执行结果都是1,事实上这个变量a被当做是window对象的一个属性了而已。再如:

function fun(){

console.log(1);

}
fun();//1
window.fun();//1

你写的所有的方法,函数,实际上就是window对象内部的一个函数而已。

那么问题来了,讲了这么半天,跟this有什么关系呢?this在英文中有指代的意味,代指“这个”。那我们把上面两段代码用this代指一下。

var a=1;
console.log(a);//1
console.log(this.a);//1
function fun(){

console.log(1);

}
fun();//1
this.fun();//1

可以看到,这段代码中我不再使用window对象,而是直接使用的this,也可以打出4个1。同样的效果,于是乎我们就知道了,当你的变量和函数外部没有任何对象时,也就是常规情况下你写的变量和方法

都暴露给window对象的时候,this代指的就是window。当然这是针对于原生js而言,像vue和微信小程序这样的mvvm框架中,这种情况下this指向undefined。

2. 现在场景换了,我们自己写了个对象,里面有一定的方法和变量,例如:

var student={
 
 name:"张三",
 age:24,
 sayhello:function(){

console.log('我是'+name,'今年'+age+'岁');

}

}

student.sayhello();

执行这段代码,结果是undefined,为啥,为啥undefined,因为fun()函数并不认识name,age,都是一个对象内部的变量,方法,怎么还就不能访问了呢?是的就是不能访问。

那怎么能访问呢?很简单,加上this,像这样写:

var student={
 
 name:'张三',
 age:24,
 sayhello:function(){

console.log('我是'+this.name,'今年'+this.age+'岁');
console.log(this);

}

}
student.sayhello();

没问题,能够执行,那我们就要想一个问题了,这里的this代表的是谁?我们不妨把他打印出来看看

打印出了一个对象,就是student这个对象。那么我们可以总结,当在对象内部使用this的时候,this指向对象本身。这个例子里面我们是自己建立的对象,实际上如果是别的对象道理也相同比如现在

是一个dom对象

<html>
<head>
</head>
<body >
<div style="width:200px;height:200px" id="bd"></div>
<button onclick="press()">按我div变红</button>
<script type="text/javascript">
function press()
{
      document.getElementById('bd').style.backgroundColor='red';
      console.log(this);//window
}
</script>
</body>
</html>

3.在上面这段代码中,js里面只有一个函数,没有新建的对象,调用这个函数的对象是button标签,隶属于window对象因此打印结果肯定是window;

4.关于回调函数中this的使用,回调函数中的this是一个特例,他不满足与前面我们提到过的理论,假设现在有这样一个场景:

var student={
 
 name:'张三',
 age:24,
 $.ajax({
 type:'GET',
 url:url,
 success:function(res){
 this.name=res.a;
 this.age=res.b;

console.log(this);
})
    }
}

还是一个对象里边,有几个属性,然后有异步请求,有一个回调函数,现在我想让回调函数里带回来的值a,b赋给对象里已经建立好的属性name,age,并且呢我还想查看一下这时候的this指向的是谁

按照之前的理论,毫无疑问这件事能够做成,name和age都能够获得值,this应该指的是当前对象,但是实践证明,不但name和age得不到应有的值

this指向的也不是当前对象。打印this你会发现结果是undefinded,这也是vue框架,包括微信小程序中经常遇到的问题。

那么首先来说原因,为什么this指向的就不是当前对象了呢。这还得从js的事件循环机制说起,异步函数通常是在方法栈中等待同步任务执行完成之后才执行的,因此当他执行结束后堆栈中的内容

又会重新刷新,这时候回调函数已经和他所在的对象分离了,所以它并不知道该指向哪,于是乎就是undefined。

那么怎么解决这个问题呢。有两种办法,第一种是在回调函数执行之前拷贝一份对象this,等结束后让它继续用这个this,像这样写:

var student={
 var _this=this;
 name:'张三',
 age:24,
 $.ajax({
 type:'GET',
 url:url,
 success:function(res){
 _this.name=res.a;
 _this.age=res.b;

console.log(_this);
})
    }
}

这样的话回调函数就能找到自己所在的对象,从而完成数据的传递。

第二种办法就是使用ES6的箭头函数。箭头函数不同于普通的函数,他的this指向它定义时所处在的对象,而不是执行时所在的对象

这样一来就不管你异步函数执行时,执行完成之后,只关心异步函数定义时所在的位置,这样就可以自然的使用this了,代码如下:

var student={
 name:'张三',
 age:24,
 $.ajax({
 type:'GET',
 url:url,
 success(res)=>{
 this.name=res.a;//光明正大的使用this,这时的this就指向student本身
 this.age=res.b;

console.log(this);
})
    }
}

实际上对于普通的回调函数无法获取this指向的问题是js的一个设计缺陷,随着ES6的诸多改进,变量以及函数的作用域划分的越来越清楚,自然也就不存在这种问题了

所以还是推荐大家尽量多使用ES6的语法去书写代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WebGIS小智

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值