最全 js this 指向问题详解。

js 在不同情况下的 this 指向问题也是难倒了很多萌新。今天小编详细讲解一下下列几种情况 this 的指向问题。

1. 普通函数调用
 function person() {
       this.name = "l";
       console.log(this);
       console.log(this.name);
 }
 person(); //输出

这种情况想必大家都知道 最后输出的是 window 和 1 。函数自执行 this 指向的是 window 。

2. 作为方法来调用
  var name="1";// 此时的 name 是属于 window 下的 name,即可以通过 window.name 访问。
  var person={
       name:"2",
       showName:function(){
   	   	 console.log(this.name);//person
   	   }
  }   
  person.showName();  //输出

此时输出的是 2 , 这里是 person 对象调用 showName 方法,很显然 this 关键字是指向 person 对象的,所以会输出 name 。

var personA={
     name:"1",
      showName:function(){
           console.log(this.name);
      }
}
var personB={
     name:"2",
     sayName:personA.showName
}
personB.sayName();  //输出

此时输出的是 2 ,你可以这么理解。将 personA.showName 这个函数赋给了personB 的 sayName。
即此时的 personB 为 :

var personB={
     name:"2",
     sayName:function(){
           console.log(this.name);
      }
}

再使用 personB 对象调用 sayName 的方法,显然 this 指向的是 personB 对象了。

3. 作为构造函数来调用
function  Person(name){
    this.name=name;
}
var personA=Person("1"); 
console.log(window.name);//输出 
console.log(personA.name); // 输出 

此时会输出 1 以及报错 error :‘name’ of undefined。在此例中 person(“1”) 相当于函数自执行,所以 this 将会指向 window 。即 this.name=name —> window.name = name。所以 personA 中并没有定义 name 属性,所以会报错。这是在没有使用实例化的情况。使用了 new 关键字实例化情况就不同了。

function  Person(name){
    this.name=name;
}
var personB=new Person("1");
console.log(personB.name);// 输出

此时输出的是 1,因为 在实例化中 this 执行实例对象,本例中实例对象为 personB。

4.call/apply方法的调用

call/apply方法最大的作用就是能改变this关键字的指向(对象冒充)。

var name="1";
var Person={
   	   name:"2",
   	   showName:function(){
   		 console.log(this.name);
   	   }
    }
Person.showName.call(); 
//这里 call 方法里面的第一个参数为空,默认指向 window 。所以这里输出的会是1.

再看一组难一点的,小伙伴们要做好准备哦。

function FnA(n1,n2){
             this.n1=n1;
             this.n2=n2;
             this.change=function(x,y){
                 this.n1=x;
                 this.n2=y;
             }
         };
var fn1=new FnA("1","2");
var fn2={
       n1:"3",
       n2:"4"
    };
fn1.change.call(fn2,"5","6");
console.log(fn2.n1); //输出
console.log(fn2.n2);// 输出

此时输出的就会是 5,6。因为 call 就是用来改变 this 指向的,即 fn1.change.call 在执行中 this 指向的是 fn2 ,即 this.n1 = x 相当于 fn2.n1 = x。x 为传过来的 5。所以最终输出的会是5。apply 方法和 call 方法是一样的,唯一不同的是传参的时候。apply 传的是数组。

fn1.change.call(fn2,"5","6");
相当于
fn1.change.apply(fn2,["5","6"]);

PS:如果能熟练使用 call 和 apply ,会为你的代码大放光彩。

5.箭头函数

es6里面this指向固定化,因为箭头函数没有this,它使用的 this 其实就是父级作用域的 this ,所以始终指向外部对象。因此它自身不能进行new实例化,同时也不能使用call, apply, bind等方法来改变this的指向。

function Timer() {
      this.seconds = 0;
      setInterval( () => this.seconds ++, 1000);//this继承父级作用域
 	}
 var timer = new Timer();
setTimeout( () => console.log(timer.seconds), 3100);

在构造函数内部的setInterval()内的回调函数,this始终指向实例化的对象, 并获取实例化对象的seconds的属性,每1s这个属性的值都会增加1。所以最终会输出 3。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值