【前端面试题】前端面试题 ——变幻莫测的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)()

最后的最后

送上最近喜欢的一句话:

因为懂得,所以慈悲!——张爱玲

©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页