js中this的指向问题

this指向问题一直困扰着我们,随着后面框架的学习,感觉有些混乱,今天好好总结一下!!

首先要明白两个问题:

1.this什么时候确定?

this在函数被调用时确定

2.this指向谁?

当前拥有this的函数被谁调用,this就指向谁

总结一句话就是:弄清拥有this的函数被谁调用

分为以下几种情形:

1)全局作用域下

直接打印this,我们可以看到它是指向window

1 console.log(this);//window 

声明一个函数,如果函数没有被调用,它里面的this我们是不知道指向的,控制台什么都没有输出

1         function fuc(){
2             console.log(this);
3         }

如果我们调用了,指向的是window

1         function fuc(){
2             console.log(this);
3         }
4         fuc();

声明一个函数并将它赋值给一个变量,然后调用,this指向window

1         var func= function(){
2             console.log(this);
3         }
4         func();

自执行函数:自执行函数就是当它被定义出来,就会自动执行的函数。它的this指向window

1      (function () {console.log(this)})();

作为函数调用时,不管你怎么嵌套,指向的是全局对象,也就是window(严格模式下,this是未定义的(undefined)

1         var func= function(){
2             console.log(this);//window
3         }
4         function say(){
5             func();
6             console.log(this);//window
7         }
8         say();

2)作为对象的方法调用时,this指向的是该方法所属的对象

1     var person = {
2     run: function () {console.log(this)}
3     }
4     person.run() // person

下面来一个复杂的例子,原理相同:

 1         var q = 'window'
 2         var func = function() {
 3             console.log(this.q)
 4         }      
 5        
 6         var obj = {
 7             q: 'obj',
 8             func: func,
 9             anotherObj: {
10                 q: 'anotherObj',
11                 func: func
12             }
13         }
14         func();//window
15         obj.func()   //obj
16         obj.anotherObj.func() //anotherObj

3)构造函数中this,指向的是构造函数新创建的这个对象。

1         function Pro(){
2             this.x = '1';
3             this.y = function(){};
4         }
5         var p = new Pro();

4)事件绑定中的this,一般情况下是指向接受该事件的元素,当然也有特殊。

事件绑定有:行内绑定,动态绑定,事件监听。

行内绑定:行内绑定事件的语法是在html节点内,以节点属性的方式绑定。

注意加粗部分:当事件触发时,属性值就会作为JS代码被执行,相当于函数调用。

1 <input type="button" value="按钮" onclick="clickFun()">
2 <script>
3     function clickFun(){
4         console.log(this);// 此函数的运行环境在全局window对象下,因此this指向window;
5     }
6 </script>
7 8 <input type="button" value="按钮" onclick="this">
9 <!-- 运行环境在节点对象中,因此this指向本节点对象 -->

动态绑定和事件监听原理相同:为节点对象的属性重新赋值一个匿名函数。

1 <input type="button" value="按钮" id="btn">
2 <script>
3     var btn = document.getElementById('btn');
4     btn.onclick = function(){
5         this ;  // this指向本节点对象
6     }
7 </script>

5)window定时器中的this

1         <script type="text/javascript">
2         var obj = {
3             fun:function(){
4                 console.log(this);
5             }
6         }
7         setInterval(obj.fun,1000);      // this指向window对象
8         setInterval('obj.fun()',1000);  // this指向obj对象
9         </script>

setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。第一个参数要调用一个代码串,也可以是一个函数。

setInterval(obj.fun,1000) 的第一个参数是obj对象的fun ,在 JS 中函数可以被当做值来做引用传递,实际就是将这个函数的地址当做参数传递给了 setInterval 方法,换句话说就是 setInterval 的第一参数接受了一个函数,那么此时1000毫秒后,函数的运行就已经是在window对象下了,也就是函数的调用者已经变成了window对象,所以其中的this则指向的全局window对象;

而在 setInterval('obj.fun()',1000) 中的第一个参数,实际则是传入的一段可执行的 JS 代码;1000毫秒后当 JS 引擎来执行这段代码时,则是通过 obj 对象来找到 fun 函数并调用执行,那么函数的运行环境依然在 对象 obj 内,所以函数内部的this也就指向了 obj 对象。

6)类似call()和apply(),bind()方法允许切换函数执行的上下文环境,可以将this引用到任何对象。

7)箭头函数中的this:箭头函数内部的this是词法作用域,由上下文确定,箭头函数没有自己的this。这里的例子来源:https://www.daqianduan.com/6790.html  ,我又做了自我解读。

箭头函数是一个普通函数:

1         var a = 0
2         var test = ()=> {
3             var a = 1
4             console.log(this.a)
5         }
      test();//0 this总是指向词法作用域,也就是该例中的外层调用者window:

箭头函数是对象的方法:

1 var a = 0
2 var obj = {
3     a: 1,
4     foo: ()=> {
5         console.log(this.a)
6     }
7 }
8 
9 obj.foo()  //0

解析上述代码:

var a =0;
var obj = new Object; obj.a = 1; obj.foo = ()=> { console.log(this.a) } obj.foo()

由于箭头函数不绑定this, 它会捕获其所在(即定义的位置)上下文的this值, 作为自己的this值,foo在全局中定义,所以this指向window。

如果想要让this指向obj这个对象我们可以这样修改

 1 var a = 0
 2 function foo(){
 3     var func = () => {
 4         console.log(this.a)
 5     }
 6     return func
 7 }
 8 var obj = {
 9     a : 1,
10     foo:foo
11 }
12 obj.foo()()  //1

在函数foo()中返回了func(),func()是在foo()被调用时定义的,所以箭头函数func()会把foo()中的this作为自己的this,而foo()是被obj调用的,拥有this的函数被谁调用this就指向谁,所以foo()的this指向obj,因此箭头函数中的this指向obj。

箭头函数是构造函数:因箭头函数没有this,固不能用作构造函数,否则会报错

1 var foo = ()=> {
2     console.log(this)
3 }
4 var boo = new foo()  //foo is not a constructor
posted @ 2021-03-15 21:56  一只蒟蒻也有大佬梦  阅读(197)  评论(0编辑  收藏  举报