this指向、箭头函数、绑定等相关问题

这其实是同一个问题,这么理解:绑定(bind)、call、apply、箭头函数其实都是为了改变this指向;换句话说,想要改变this指向,可以用这几种方式:.bind()、.call()、.apply()、箭头函数。

一、函数的调用中的this指向问题(调用方式不同,this指向也不同)

1.普通函数调用,此时 this 指向 window

    function fn() {
       console.log(this);   // window
     }
     fn();  //  window.fn(),此处默认省略window

2.构造函数调用, 此时 this 指向 实例对象

 function Person(age, name) {
         this.age = age;
         this.name = name
         console.log(this)  // 此处 this 分别指向 Person 的实例对象 p1 p2
     }
    var p1 = new Person(18, 'zs')
    var p2 = new Person(18, 'ww')

突然醒悟,这里跟java后台很像,如下:

//Student类
public class Student{
	public String name;	
	public Int age;
}

Student st = new Student('zs',16)
system.outprint(st.name)//zs

3.对象方法调用, 此时 this 指向 该方法所属的对象

 var obj = {
       fn: function () {
         console.log(this); // obj
       }
     }
    obj.fn();

4.通过事件绑定的方法, 此时 this 指向 绑定事件的对象

<body>
    <button id="btn">hh</button>
<script>
    var oBtn = document.getElementById("btn");
    oBtn.onclick = function() {
        console.log(this); // btn
    }
</script>
</body>

5.定时器函数, 此时 this 指向 window

 setInterval(function () {
       console.log(this); // window
     }, 1000);

二、更改this指向的三个方法

1.call() 方法

 var Person = {
        name:"lixue",
        age:21
    }
function fn(x,y){
    console.log(x+","+y);
    console.log(this);
}
fn("hh",20);

没错,就像上面说的,普通函数的this指向window,现在让我们更改this指向

 var Person = {
        name:"lixue",
        age:21
    }
function fn(x,y){
   console.log(x+","+y);
   console.log(this);
   console.log(this.name);
   console.log(this.age);
}
fn.call(Person,"hh",20);

看,现在this就指向person了
call方法除了第一个参数以外还可以添加多个参数,如下:

var a = {
    user:"taro",
    fn:function(e,ee){
        console.log(this.user); //taro
        console.log(e+ee); //3
    }
}
var b = a.fn;
b.call(a,1,2);

2.apply() 方法
apply() 与call()非常相似,也可以有多个参数,不同之处在于提供参数的方式,apply()使用参数数组,如下:

var a = {
    user:"追梦子",
    fn:function(e,ee){
        console.log(this.user); //追梦子
        console.log(e+ee); //11
    }
}
var b = a.fn;
b.apply(a,[10,1]);
//注意如果call和apply的第一个参数写的是null,那么this指向的是window对象
var a = {
    user:"追梦子",
    fn:function(){
        console.log(this); //Window {external: Object, chrome: Object, document: document, a: Object, speechSynthesis: SpeechSynthesis…}
    }
}
var b = a.fn;
b.apply(null);

3.bind()方法
bind()创建的是一个新的函数(称为绑定函数),与被调用函数有相同的函数体,当目标函数被调用时this的值绑定到 bind()的第一个参数上
bind方法和call、apply方法有些不同,如下:

var a = {
    user:"taro",
    fn:function(){
        console.log(this.user);
    }
}
var b = a.fn;
b.bind(a);  //代码没有被打印

我们发现代码没有被打印,对,这就是bind和call、apply方法的不同,实际上bind方法返回的是一个修改过后的函数。

var a = {
    user:"追梦子",
    fn:function(){
        console.log(this.user);
    }
}
var b = a.fn;
var c = b.bind(a);
console.log(c); //function() { [native code] }

函数c看看,能不能打印出对象a里面的user


var a = {
    user:"追梦子",
    fn:function(){
        console.log(this.user); //追梦子
    }
}
var b = a.fn;
var c = b.bind(a);
c();

同样bind也可以有多个参数,并且参数可以执行的时候再次添加,但是要注意的是,参数是按照形参的顺序进行的。

var a = {
    user:"追梦子",
    fn:function(e,d,f){
        console.log(this.user); //追梦子
        console.log(e,d,f); //10 1 2
    }
}
var b = a.fn;
var c = b.bind(a,10);
c(1,2);

例:定时器使用.bind()改变this指向

 var oDiv1 = document.getElementById("div1");
    oDiv1.onclick = function(){
        setTimeout(function(){
            console.log(this);
        },1000)
    }
 var oDiv1 = document.getElementById("div1");
    oDiv1.onclick = function(){
        setTimeout(function(){
            console.log(this);
        }.bind(this),1000)
    }

因为在定时器外,在绑定事件中的this肯定指向绑定事件的对象div啊,用call和apply都行

三、箭头函数

看个例子

var o = {
      a:10,
      b:{
          a:12,
          fn:function(){
              console.log(this);//b   {a: 12, fn: ƒ}
          }
      },
      fn1:function(){
          console.log(this.a);  //10
      }
  }
  o.fn1();
  o.b.fn();
var o = {
      a:10,
      b:{
          // a:12,
          fn:()=>{
              console.log(this);//window
          }
      },
      fn1:function(){
          console.log(this.a);  //10
      }
  }
  o.fn1();
  o.b.fn();

把普通函数换成箭头函数过后,this的指向也发生了变化,原因是:
箭头函数:箭头函数本身是没有this和arguments的,在箭头函数中引用this实际上是调用的是定义时的上一层作用域的this。
这里强调的是上一层作用域,是因为对象是不能形成独立的作用域的。

思考: 那么,想让o.b.fn()打印出来的this指向o对象,该怎么改?

var o = {
      a:10,
      b:function(){
          // a:12,
          var fn=()=>{
              console.log(this);//o   {a: 10, b: ƒ, fn1: ƒ}
          }
          fn()
      },
      fn1:function(){
          console.log(this.a);  //10
      }
  }
  o.fn1();
  o.b();

参考文档:
https://blog.csdn.net/xuehangongzi/article/details/80841167
https://blog.csdn.net/qq_37467034/article/details/78311591

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值