JavaScript中this的指向

110 阅读3分钟

this的指向

this指向的原则:始终指向最后调用它的对象

看个简单的例子:

var name = "wN";
function fn() {
    var name = "Jack";
    console.log(this.name);          // wN
}
fn();

根据this指向原则:始终指向最后调用它的对象,最后调用fn()这里,前面没有调用的对象那么就是全局对象 window,所以相当于window.fn()

接着看例子:

var name = "wN";
var a = {
    name: "Jack",
    fn : function () {
        console.log(this.name);      // Jack
    }
}
a.fn();

在这里,函数 fn 是对象 a 调用的,所以打印的值就是 a 中的 name 的值,对this是不是有了初步的认识。

var name = "wN";
var a = {
    name: "Jack",
    fn : function () {
        console.log(this.name);      // Jack
    }
}
window.a.fn();

这里打印的也是Jack,还是因为this指向原则,window.a.fn()最后调用的对象是a,this指向a对象中的name。

改变this的指向

改变this的指向有几种方法:

  • 在函数内部使用 _this = this
  • 使用 apply、call、bind
  • 使用 ES6 的箭头函数
  • new 实例化一个对象

下面逐一展开说说

使用 _this = this

var a = {
    name : "Jack",
    func1: function () {
        console.log(this.name)     
    },
    func2: function () {
        var _this = this;
        setTimeout( function() {
            // this.fun1()       //  this.fun1 is not a function
            _this.func1()    //   Jack
        },100);
    }
};

a.func2()       // Jack

我们是先将调用这个函数的对象保存在变量中,然后在函数中都使用这个变量var _this = this,这是最简单的方式。

使用apply、call、bind

apply

var a = {
    name : "Jack",
    func1: function () {
        console.log(this.name)
    },
    func2: function () {
        setTimeout(  function () {
            this.func1()
        }.apply(a),100);  //call同理
    }
}
a.func2()     // Jack

bind

var a = {
    name : "Jack",
    func1: function () {
        console.log(this.name)
    },
    func2: function () {
        setTimeout(  function () {
            this.func1()
        }.bind(a)(),100);
    }
}
a.func2()     // Jack

apply、call、bind 区别

apply 和 call 类似,只是两者之间传递的参数不同。

apply(thisArg, argsArray)
call(thisArg, arg1, /* …, */ argN)

都是两个参数,第一个参数两者都为this调用时使用的值func,第二个参数,apply是数组,call是参数列表,直接传。

var a ={
    fn : function (a,b) {
        console.log(a,b)
    }
}
var b = a.fn;
b.apply(a,[1,2])     // 1,2
var a ={
    fn : function (a,b) {
        console.log(a,b)
    }
}
var b = a.fn;
b.call(a,1,2)     // 1,2

bind函数创建一个新的绑定函数,同时它的参数如下:

bind(thisArg, arg1, arg2)
第一个参数两者都为`this`调用时使用的值`func`,第二个参数是参数列表
var a ={
    fn : function (a,b) {
        console.log(a,b)
    }
}
var b = a.fn;
// b.bind(a,1,2)     // 无输出
b.bind(a,1,2)()      // 根据bind会创建一个新的绑定函数,所以需要手动调用

箭头函数

ES6箭头函数里this指向外层,也就是上一层

var obj = {
   num: 10,
   fn: function () {
    console.log(this);    // obj
    setTimeout(function () {
      console.log(this);    // window
    });
   }    
}
obj.fn()

在上面的例子中,第一个this指向obj,因为fn的调用者是obj,而setTimeout里是匿名函数,没有直接调用者,所以this指向window。

var obj = {
   num10,
   fnfunction () {
    console.log(this);    // obj
    setTimeout(() => {
      console.log(this);    // obj
    });
   }    
}
obj.fn();

第一个this指向obj,setTimeout箭头函数,this指向外层,所以也是obj

new 实例化一个对象

直接看例子:

function fn(){
    console.log(this);
}
fn();   // window
let obj=new fn();   // fn()

使用new实例化对象时,this代表被实例化的对象。

这就是this的指向,当然,也有复杂的场景,这里就不去过多的讲解了,用简单的例子带你认识 this 同时希望我的文章能对你有所帮助,有什么不对的地方可以评论指出。