JS函数中的this指向问题

来源:互联网 发布:液晶编程器烧录器 编辑:程序博客网 时间:2024/06/08 08:34

今天我要说的是JS中的this指向,首先我们应该知道在js中函数的几种调用方式:

  1. 普通函数调用
  2. 作为方法来调用
  3. 作为构造函数来调用
  4. 使用apply/call方法来调用
  5. Function.prototype.bind方法
  6. es6箭头函数

不管是通过哪种方式函数调用,我们都应该明确一点谁调用这个函数或方法,this关键字就指向谁。
1.普通函数调用

function person(){    this.name="lx";    console.log(this);//window    console.log(this.name);//lx}person();console.log(window.name);//lx

在这段代码中person函数作为普通函数调用,实际上person是作为全局对象window的一个方法来进行调用的,即window.person(),所以这个地方是window对象调用了person方法,那么person函数当中的this即指window,同时window还拥有了另外一个属性name,值为lx,我在最后也输出了window.name即lx。
2.作为方法来调用

var name="lx";var person={    name:"jay",    showName1:function(){        console.log(this.name);    }}person.showName1();//jayvar showName2=person.showName1;showName2();//lx第一个是的person对象调用showName1方法,所以this指向person对象,所以输出jay,第二个将person.showName1方法赋值给showName2变量,此时showName2变量相当于window对象的一个属性,相当于window.showName2,所以this指向的是window,输出lx
var personA={    name:"lx",       showName:function(){           console.log(this.name);//jay       }}var personB={    name:"jay",    sayName:personA.showName}    personB.sayName();

这里的showName方法肃然是在personA这个对象中定义,但是调用的时候却是在personB这个对象中调用,因此this对象指向的是personB
3.作为构造函数调用

function  Person(name){    this.name=name;}var personA=Person("lx");console.log(personA.name); //会报错console.log(window.name);//输出lx//上面代码没有进行new操作,相当于window对象调用Person("lx")方法,那么this指向window对象,并进行赋值操作window.name="lx".var personB=new Person("lx");console.log(personB.name);// 输出lx

new操作符

function person11(name){    var o={};    o.__proto__=Person.prototype;  //原型继承    Person.call(o,name);    return o;}var personB=person11("lx");console.log(personB.name);  // 输出  lx

上面这段代码模拟了new操作符(实例化对象)的内部过程
4.call/apply方法的调用
在JS里,函数也是对象,因此函数也有方法,从Function.prototype上继承到Function.prototype.call/Function.prototype.apply方法。
call/apply方法最大的作用就是能改变this关键字的指向。

var name="jay";var Person={    name:"lx",    showName:function(){        console.log(this.name);    }}    Person.showName.call(Person); //输出lx    Person.showName.call();//输出 jay

虽然showName方法定义在Person对象里面,但是使用call方法后,将showName方法里面的this指向了window,因此最后会输出jay,这里call方法里面的参数为空,默认指向window。
5. Function.prototype.bind方法

var name="jay";function Person(name){    this.name=name;    this.sayName=function(){        setTimeout(function(){            console.log("my name is "+this.name);        },50)    }}var person=new Person("lx");person.sayName(); //输出my name is jay//这里的setTimeout()定时函数,相当于window.setTimeout(),由window这个全局对象对调用,因此this的指向为window, 则this.name则为jay

难么该怎么输出my name is lx?

var name="jay";function Person(name){    this.name=name;    this.sayName=function(){        setTimeout(function(){            console.log("my name is "+this.name);        }.bind(this),50)//这个地方使用的bind()方法,绑定setTimeout里面的匿名函数的this一直指向Person对象    }}var person=new Person("lx");person.sayName(); //输出my name is lx

这里setTimeout(function(){console.log(this.name)}.bind(this),50);,匿名函数使用bind(this)方法后创建了新的函数,这个新的函数不管在什么地方执行,this都指向的Person,而非window,因此最后的输出为my name is lx而不是my name is jay。
这里的第六种方法是 es6箭头函数,es6的内容看的稍微有点少,理解的不是很全面,所以我就不再做详细的书写了,感兴趣的大牛可以度娘了解一下。