this指向问题(call,apply,bind)

378 阅读2分钟

在es5中:this永远指向最后调用它的对象

改变this指向:

  1. 使用ES6箭头函数
  2. 在函数内部使用_this = this;
  3. 使用apply, call, bind
  4. new实例化一个对象

箭头函数的 this 始终指向函数定义时的 this,而非执行时。

1)箭头函数

“箭头函数中没有 this 绑定,必须通过查找作用域链来决定其值,如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this,否则,this 为 undefined”。

2)_this = this;

先将调用这个函数的对象保存在变量_this中,然后在函数中都使用这个_this,这样_this就不会改变了。

    var name = "windowsName";
    var a = {
        name : "Cherry",

        func1: function () {
            console.log(this.name)     
        },

        func2: function () {
            var _this = this;
            setTimeout( function() {
                _this.func1()
            },100);
        }
    };
    a.func2()       // Cherry

在 func2 中,首先设置 var _this = this;,这里的 this 是调用 func2 的对象 a,为了防止在 func2 中的 setTimeoutwindow 调用而导致的在 setTimeout 中的 thiswindow。我们将 this(指向变量 a) 赋值给一个变量 _this,这样,在 func2 中我们使用 _this 就是指向对象 a 了。

使用call、apply、bind

使用apply

    var a = {
        name : "Cherry",

        func1: function () {
            console.log(this.name)
        },

        func2: function () {
            setTimeout(  function () {
                this.func1()
            }.apply(a),100);//apply在这里
        }
    };
    a.func2()            // Cherry

使用call

同apply

使用bind

    var a = {
        name : "Cherry",

        func1: function () {
            console.log(this.name)
        },

        func2: function () {
            setTimeout(  function () {
                this.func1()
            }.bind(a)(),100);
        }
    };
    a.func2()            // Cherry

apply, call, bind 区别

apply语法:

fun.apply(thisArg, [argsArray])
  • thisArg:在 fun 函数运行时指定的 this 值。
  • argsArray:一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。

apply 与 call 区别

apply 与 call基本类似,区别是传入的参数不同: call语法:

fun.call(thisArg[, arg1[, arg2[, ...]]])

所以 apply 和 call 的区别是 call 方法接受的是若干个参数列表,而 apply 接收的是一个包含多个参数的数组。

//apply
    var a ={
        name : "Cherry",
        fn : function (a,b) {
            console.log( a + b)
        }
    }

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

    var b = a.fn;
    b.call(a,1,2)       // 3

bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。

所以我们可以看出,bind 是创建一个新的函数,我们必须要手动去调用:

    var a ={
        name : "Cherry",
        fn : function (a,b) {
            console.log( a + b)
        }
    }

    var b = a.fn;
    b.bind(a,1,2)()           // 3