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