变幻莫测的this指向
前言: 我自己在开课吧app购买的一套前端课程,感觉非常好,所以,我利用[每日一更]来把它记录下来。互联网的精神就是开源啊,所以,把重点的知识记录下来方便大家进行学习。
this指向—— 事件和全局
总结:
事件调用环境:谁触发事件,函数里面的this就指向谁;
全局调用环境:1, 在浏览器的环境下,this指向的是window
2, 在nodejs的环境下,this 指向的module.exports
用代码来看一下吧!帮助理解
事件
类比王者荣耀
当定义一个英雄box (小方块进行移动)
<style>//给英雄定义样式等
.box{
width:100px;
height:100px;
background:#0A8CD2;
position:relative;
left:0;
transition:Is;//过渡
}
</style>
<body>
<div class ="box"></div>//定义一个英雄box
<script>
let box = document.querySelector('.box');
box.onclick = move;
function move(){
box.style.left = '100px';
}
</script>
</body>
当添加两个英雄的时候(box和lili)
<div class ="box"></div>//定义一个英雄box
<div class = 'lili'></div>
<script>
let box = document.querySelector('.box');
box.onclick = move;
lili.onclick = move;
</script>
function move(){
box.style.left = '100px';
当我们再次点击lili图像的时候,我们会发现 box图像在移动,这时候,我们需要把这里的box改为this 用this指向谁则谁就动。
function move(){
box.style.left = '100px';
改为
function move(){
this.style.left = '100px';
总结:事件调用环境,谁触发事件,函数里面的this就指向谁。
全局:
在函数的外面直接加上
console.log(this);
总结:1, 在浏览器上直接显示的是window
在node上显示:
在创建一个this.js
console.log(this);
在命令行中输入
node this.js
运行的时候 显示的是一个空的对象({ })
这个时候我们把刚刚创建的this.js改为
console.log(this=== module.exports);
运行的是时候,显示的是一个true
总结:在浏览器的环境下,this指向的是window
在nodejs环境下,this指向的是module.exports
this指向——函数和对象
第一种情况:直接利用函数去调用
funnction move(){
console.log(this);
this.style.left = '100px';
}
move();//指向的是window 更准确的是 undefined
window.move();//严格情况下 依然指向的是window
var abc = 10;//定义一个abc为 10
console.log(window)//可以从window下查看到abc 为10
总结:当函数自己调用的时候,this指向的就是window
第二种情况:
<script>
var obj = {
a : 10;
b : function(){
console.log(this);
}
}
obj.b();//我们调用b的时候,this指向的是obj
window.obj.b();//this指向的是obj
</script>
总结:
1, this最终指向的是调用它的对象(obj.b()的指向)
== 2, 如果函数被外层对象调用,this也指向的是它上一级对象(window.obj.b()的指向)==
第三种情况
<script>
var obj = {
a : 10;
b:{
fn:function(){
console.log(this);//在定义和声明的时候,里面的this是没有意义的 只有在被调用的时候 才有意义
}
}
}
var abc = obj.b.fn;//fn未被调用则里面的this没有意义
window.obj.b.fn();//fn被调用了则this有意义 则this就指向b
abc();//调用的是函数本身 其实是省略了window.abc();省略了window的调用对象 在里面起全局的,所以,this指向是window
</script>
总结:this最终指向的是 调用它的函数(和声明没有关系)
this指向——构造函数
<script>
function fn(){
this.num = 10;
console.log(this);//构造函数的this指向空的对象
}
fn.num = 20;
fn.prototype.num = 30;
fn.prototype.method = function(){
console.log(this.num);
}
var prototype = fn.prototype;
var method = prototype.method;
new fn().method();//10
prototype.method();//30
method();//window - undefined
var obj = new fn();//作为构造函数需要赋值 用new来调用fn函数
console.log (obj.num);//这里的obj和上面的this一样 可以拿到数字
//运行显示为
fn{
num :10}
num : 10
_proto_:object
/* new 的作用
* 1,调用函数
* 2,自动创建一个对象
* 3,把创建出来的对象 this进行绑定
* 4,如果构造函数 没有返回值 就返回this的值
* */
</script>
this指向——构造函数(遇上return)
<script>
function fn(){
this.num = 10;
return '';//空字符串:10/[]数组:undefined/{}对象:undefined/1:10
}
var obj = new fn();
console.log(obj.num);
</script>
return返回值为:
空字符串 刷新运行结果为 10
数组 刷新运行结果为 undefined
对象 刷新运行结果为 undefined
1 刷新运行结果为 10
总结:
返回出来的不是一个对象 则this指向的是实体化对象
返回出来的是一个对象 则this指向的是返回的对象
<script>
function fn(){
this.num = 10;
return {
num:20;//指向为20(指向了返回本身)
}
return 1//指向为10
return null//指向为10
}
var obj = new fn();
console.log(obj.num);
</script>
总结:
如果构造函数中有return 如果return 的值对象,this指向返回的对象,如果不是对象,则this保持原来的规则,其中 null比较特殊
this指向——箭头函数
function move(){
setTimeout(function(){
//加一个计时器
this.style.left = '100px';
},1000)
console.log(this);//执行不出来了
//出来了箭头函数改为
function move(){
setTimeout(()=>{
this.style.left = '200px';
},1000);
console.log(this);//即可执行出来
//官方文档中说,this根据上下文环境决定的
}
}
总结:
箭头函数本身是没有this和argument的,在箭头函数中引用this实际上调用的是定义上一层作用域的this。这里强调一下是上一层作用域,因为对象是不能形成独立的作用域的
call apply bind三种方法修改this指向
<script>
var box = document.querySelector('.box')
var obj = {
fn:()=>{
console.log(this);//已经指向了window 后面的call修改没有用
}
}
//修改为
fn:function(){
console.log(this);
}
obj.fn.call(box,a,b,c);//指向的是box call可以传修改修改的参数
obj.fn.apply(box,[a,b,c])//apply也可以传参必须为数组
obj.bind(box)()//修改this指向
</script>
总结:
call apply 以及bind三种方法都可以修改this指向,但是传参的方式不同
call(this,a,b,c)
apply(this[a,b,c])
bind(this,a,b,c)()
最后的最后
送上最近喜欢的一句话:
因为懂得,所以慈悲!——张爱玲