call()、apply()和bind()用法和区别

相同点:call()、apply()和bind()都可以改变函数内部的this指向
不同点请看下面实例:

call():

call方法既可以调用函数,又可以改变函数内的this指向。

var obj = {
	name: 'andy'
}
function fn(a, b) {
console.log(this);
console.log(a+b)
};
fn(1,2)// 此时的this指向的是window 运行结果为3
fn.call(obj,1,2)//此时的this指向的是对象obj,参数使用逗号隔开,运行结果为3

应用场景: 经常做继承。参考下面这篇讲原型链的末尾部分:https://blog.csdn.net/caipital/article/details/108396438
出一个面试题:

function f1(a,b){
    console.log(this)  //输出f2
    console.log(a+b)	//输出3
}
function f2 (a,b) {
    console.log(this)
    console.log(a-b)
}
f1.call(f2,1,2)		//打印输出f2 和 3

apply()

call方法既可以调用函数,又可以改变函数内的this指向。与call()的区别是函数调用时参数是数组

function fn(a,b){
    console.log(this)  
    console.log(a+b)
}
let obj = {
    name:'zy'
}
fn.apply(obj,[1,2]) //此时的this指向的是对象obj,参数传入了一个数组,运行结果为3

应用场景:数组运用到Math的API中

let a = Math.max(9,21,33);
console.log(a)   //33

let arr = [9,21,33];
let res1 = Math.max(...arr)  
let res2 = Math.max.apply(null,arr); 
let res3 = Math.max.apply(Math,arr);   // 推荐  
let res4 = Math.max.apply(Function,arr);  

console.log(res1)    //33
console.log(res2)    //33
console.log(res3)    //33
console.log(res4)    //33

bind()

bind()改变函数this指向,但不调用函数,会生成一个新的函数

 function fn(a,b){
     console.log(this)  
     console.log(a+b)
 }
 let obj = {
     name:'zy'
 }
 let new_fn1 = fn.bind(obj)
 new_fn1(2,3)    //this指向obj 打印输出5
 let new_fn2 = fn.bind(obj,1,2)
 new_fn2()   //this指向obj 打印输出3

应用场景:当你想改变函数的this指向同时又不想立即执行函数的时候。
举个例子,一道经典面试题,在此题中体会bind()的用法吧。

要求:给三个按钮绑定点击事件,点击之后按钮变成不可点的状态,1秒之后恢复,变成可点击的状态。

方案一 :let 块级作用域

for(let i =0;i<btns.length;i++) {
    btns[i].onclick = function() {
        //表达式函数this指向绑定事件的对象
        this.disabled = true;
        setTimeout(function(){
            btns[i].disabled = false;
        },1000)
    }
}

方案二:使用自调用函数(闭包思想)
闭包(closure):指有权访问另一个函数作用域中变量的函数。

for (var i = 0; i < btns.length; i++) {
    (function (i) {
        btns[i].onclick = function () {
            //表达式函数this指向绑定事件的对象
            this.disabled = true;
            setTimeout(function () {
                console.log(this)   //Window
                btns[i].disabled = false;
            }, 1000)
        }
    })(i)
}

方案三: var that = this,储存this(闭包)

for(var i =0;i<btns.length;i++) {
    btns[i].onclick = function() {
        //表达式函数this指向绑定事件的对象
        this.disabled = true;
        var that = this;
        setTimeout(function(){
            that.disabled = false;
        },1000)
    }
}

方案四:使用 bind()改变this指向

for(var i =0;i<btns.length;i++) {
    btns[i].onclick = function() {
        //表达式函数this指向绑定事件的对象
        this.disabled = true;
        setTimeout(function(){
            this.disabled = false;
        }.bind(this),1000)
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值