如何改变this的指向

我心飞翔 分类:javascript

这是我参与更文挑战的第3天,活动详情查看: 更文挑战

如何改变this的指向呢?ECMAScript规范里面给了我们两种方法,call与apply方法。但是这两种方法有什么区别呢?可以说call与apply在作用上一摸一样,只是有传参数的不同。

apply()

apply方法传入两个参数:第一个是函数上下文的对象,第二个是一个作为函数参数所组成的数组。

    var obj = {
        name : 'dddd'
    }

    function func(firstName, lastName){
        console.log(firstName + ' ' + this.name + ' ' + lastName);
    }

    func.apply(obj, ['A', 'B']);    // A dddd B
    
 

我们可以看到obj作为func的函数上下文的obj。func中的this指向obj。参数 A 和 B 是放在数组中传入 func 函数,分别对应 func 参数的列表元素。

call( )

call 方法第一个参数也是作为函数上下文的对象,但是后面传入的是一个参数列表,而不是单个数组。

    var obj = {
        name: 'dddd'
    }

    function func(firstName, lastName) {
        console.log(firstName + ' ' + this.name + ' ' + lastName);
    }

    func.call(obj, 'C', 'D');       // C dddd D
    
 

对比 apply 我们可以看到区别,C 和 D 是作为单独的参数传给 func 函数,而不是放到数组中。

所以我们对于什么时候该用什么方法,其实不用纠结。如果你的参数本来就存在一个数组中,那自然就用 apply,如果参数比较散乱相互之间没什么关联,就用 call。

apply 和 call 的用法

1.改变 this 指向

    var obj = {
     name: 'dddd'
 }

 function func() {
     console.log(this.name);
 }

 func.call(obj);       // dddd

// 我们都知道call的第一个参数是函数上下文的对象,这里把obj传给func相当于函数里的 this //便指向了 obj 对象。
func(){
    console.log(obj.name)
}

 

2.调用函数

apply、call 方法都会使函数立即执行,因此它们也可以用来调用函数。

    function func() {
        console.log('dddd');
    }
    func.call();//这里我们调用func.call()相当于直接执行func函数,会直接打印dddd
 

3.bind方法

    if (!Function.prototype.bind) {
     Function.prototype.bind = function () {
         var self = this,                        // 保存原函数
             context = [].shift.call(arguments), // 保存需要绑定的this上下文
             args = [].slice.call(arguments);    // 剩余的参数转为数组
         return function () {                    // 返回一个新函数
             self.apply(context,[].concat.call(args, [].slice.call(arguments)));
         }
     }
 }
 

这里我们自己实现了bind的方法。留一个作业,随后一行的self.apply(context,[].concat.call(args, [].slice.call(arguments)));中apply的参数为何不是args而是要[].concat.call(args, [].slice.call(arguments))这样。可以把你的想法留在评论区。。。

从输出可以看出args是f.binding里除了第一个参数剩下所有的参数,而[].slice.call(arguments)是f.binding后第二个括号里的参数,args的this是Function.prototype.binding,[].slice.call(arguments)的this是f.binding(obj)()。\color{#FFFFFF}{从输出可以看出 args 是 f.binding 里除了第一个参数剩下所有的参数,而 [].slice.call(arguments) 是 f.binding 后第二个括号里的参数, args 的 this 是 Function.prototype.binding,[].slice.call(arguments) 的 this 是 f.binding(obj)()。}

回复

我来回复
  • 暂无回复内容