前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >js this问题和es6箭头函数this问题

js this问题和es6箭头函数this问题

作者头像
yaphetsfang
发布2020-07-30 09:49:42
1.3K0
发布2020-07-30 09:49:42
举报
文章被收录于专栏:yaphetsfangyaphetsfang

JS中this的四种用法

1.在一般函数方法中使用 this 指代全局对象

代码语言:javascript
复制
function test(){
    this.x = 1;
    alert(this.x);
  }
  test(); //1

2.作为对象方法调用,this 指代上级对象

代码语言:javascript
复制
function test(){
  alert(this.x);
}
var o = {};
o.x = 1;
o.m = test;
o.m(); // 1

3.作为构造函数调用,this 指代new 出的对象

代码语言:javascript
复制
 function test(){
    this.x = 1;
  }
  var o = new test();
  alert(o.x); // 1
    //运行结果为1。为了表明这时this不是全局对象,我对代码做一些改变:
  var x = 2;
  function test(){
    this.x = 1;
  }
  var o = new test();
  alert(x); //2

4.apply 调用 ,apply方法作用是改变函数的调用对象,此方法的第一个参数为改变后调用这个函数的对象,this指代第一个参数

代码语言:javascript
复制
  var x = 0;
  function test(){
    alert(this.x);
  }
  var o={};
  o.x = 1;
  o.m = test;
  o.m.apply(); //0
//apply()的参数为空时,默认调用全局对象。因此,这时的运行结果为0,证明this指的是全局对象。如果把最后一行代码修改为

  o.m.apply(o); //1

ES6中箭头函数与普通函数this的区别

普通函数中的this:

1. this总是代表它的直接调用者, 例如 obj.func ,那么func中的this就是obj

2.在默认情况(非严格模式下,未使用 'use strict'),没找到直接调用者,则this指的是 window

3.在严格模式下,没有直接调用者的函数中的this是 undefined

4.使用call,apply,bind(ES5新增)绑定的,this指的是 绑定的对象

箭头函数中的this

默认指向在定义它时,它所处的对象,而不是执行时的对象, 定义它的时候,可能环境是window(即继承父级的this);

下面通过一些例子来研究一下 this的一些使用场景

示例1

代码语言:javascript
复制
<script>
  var obj = {
    say: function () {
      setTimeout(function () {
        console.log(this)
      });
    }
  }
  obj.say();
</script>

结果是:window

匿名函数,定时器中的函数,由于没有默认的宿主对象,所以默认this指向window

问题: 如果想要在setTimeout中使用这个对象的引用呢?

用一个 变量提前把正确的 this引用保存 起来, 我们通常使用that = this, 或者 _this = this来保存我们需要的this指针!

代码语言:javascript
复制
<script>
  var obj = {
    func: function() {},
    say: function () {
      var that = this;   //此时的this就是obj对象
      setTimeout(function () {
        console.log(this)
        that.func()
      });
    }
  }
  obj.say();
</script>

示例2

代码语言:javascript
复制
window.val = 1;
var obj = {
  val: 2,
  dbl: function () {
    this.val *= 2;
    val *= 2;
    console.log(val);
    console.log(this.val);
  }
};
// 说出下面的输出结果
obj.dbl();
var func = obj.dbl;
func();

结果是:2  4  8  8

<1> 12行代码调用

val变量在没有指定对象前缀,默认从函数中找,找不到则从window中找全局变量

即 val *=2 就是 window.val *= 2

this.val默认指的是 obj.val ;因为 dbl()第一次被obj直接调用

<2>14行代码调用

func() 没有任何前缀,类似于全局函数,即  window.func调用,所以

第二次调用的时候, this指的是window, val指的是window.val

第二次的结果受第一次的影响

示例3.在严格模式下的this

代码语言:javascript
复制
<script>
  function test() {
    'use strict';
    console.log(this);
  }
  test();
</script>

结果是:undefined

示例4.箭头函数中的this

代码语言:javascript
复制
<script>
  var obj = {
    say: function () {
      setTimeout(() => {
        console.log(this)
      });
    }
  }
  obj.say(); // obj
</script>

 此时的this是定义它的对象,即继承父级的this,父级中的this指的是obj,而非window

示例5

代码语言:javascript
复制
<script>
  var obj = {
    say: function () {
      var f1 = () => {
        console.log(this); // obj
        setTimeout(() => {
          console.log(this); // obj
        })
      }
      f1();
    }
  }
  obj.say()
</script>

结果:都是obj

f1继承父级this指代的obj,不管f1有多层箭头函数嵌套,都是obj.

示例6

代码语言:javascript
复制
<script>
  var obj = {
    say: function () {
      var f1 = function () {
        console.log(this);    // window, f1调用时,没有宿主对象,默认是window
        setTimeout(() => {
          console.log(this); // window
        })
      };
      f1();
    }
  }
  obj.say()
</script>

结果:window,window

第一个this:f1调用时没有宿主对象,默认是window

第二个this:继承父级的this,父级的this指代的是window

关于this指向问题的讨论一直是学习js不可忽视的重要部分,那些一个又一个围绕this挖的笔试坑,仿佛永远也填不完

代码语言:javascript
复制
 
var obj={
 
fn:function(){
 
console.log(this);
 
}
 
} 
obj.fn();//object

以上这段代码是再浅显不过的this指向问题,也就是谁调用的函数,函数体中的this就指向谁

再看下面这段

代码语言:javascript
复制
var obj={
 
fn:function(){
 
setTimeout(function(){
 
console.log(this);
 
});
 
}
} 
obj.fn();//window

这次this指向了最外层的window对象,为什么呢,还是那个道理,这次this出现在全局函数setTImeout()中的匿名函数里,并没有某个对象进行显示调用,所以this指向window对象

假如我们在这里使用箭头函数呢

代码语言:javascript
复制
 
var obj={
 
fn:function(){
 
setTimeout(() => {
 
console.log(this);
 
});
 
}
 
}
 
obj.fn();//object

this又指向函数的宿主对象了

为了更加清楚的对比一般函数和箭头函数this指向的区别,我们给对象添加变量

代码语言:javascript
复制
 
var obj={
 
num:3,
 
fn:function(){
 
setTimeout(function(){
 
console.log(this.num);
 
});
 
}
 
}
 
obj.fn();//undefined
 
//............................................................
 
var obj1={
 
num:4,
 
fn:function(){
 
setTimeout(() => {
 
console.log(this.num);
 
});
 
}
 
}
 
obj1.fn();//4

如上代码,在没有使用箭头函数的情况下,this指向了window(匿名函数,没有调用的宿主对象),而window对象并没有num属性(num属性在obj中定义),而在使用箭头函数的情况下,this的指向却对象obj1,自然可以输出obj1中定义的属性num。

接下来看更复杂的情况

多层嵌套的箭头函数

代码语言:javascript
复制
 
var obj1={
 
num:4,
 
fn:function(){
 
var f=() => { //object,也就是指obj1
 
console.log(this);
 
setTimeout(() => {
 
console.log(this);// //object,也就是指obj1
 
});
 
}
 
f();
 
}
 
}
 
obj1.fn();

假如我们改动两层箭头函数的其中一处,看会出现什么结果

代码语言:javascript
复制
 
var obj1={
 
num:4,
 
fn:function(){
 
var f=function(){
 
console.log(this); //window,因为函数f定义后并没有对象调用,this直接绑定到最外层的window对象
 
setTimeout(() => {
 
console.log(this);//window,外层this绑定到了window,内层也相当于定义在window层(全局环境)
 
});
 
}
 
f();
 
}
 
}
 
obj1.fn();

好,接下来改变另一处

代码语言:javascript
复制
 
var obj1={
 
num:4,
 
fn:function(){
 
var f=() => {
 
console.log(this); //object,f()定义在obj1对象中,this就指向obj1,这就是箭头函数this指向的关键
 
setTimeout(function() {
 
console.log(this);//window,非箭头函数的情况下还是要看宿主对象是谁,如果没有被对象调用,函数体中的this就绑定的window上
 
});
 
}
 
f();
 
}
 
}
 
obj1.fn();

总结:

1.箭头函数的this绑定看的是this所在的函数定义在哪个对象下,绑定到哪个对象则this就指向哪个对象

2.如果有对象嵌套的情况,则this绑定到最近的一层对象上

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-07-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JS中this的四种用法
  • ES6中箭头函数与普通函数this的区别
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档