call和apply

138 阅读2分钟

call、apply、bind this指针,在ES5中指向的是调用它的对象

什么是指针?

1. 介绍this指针

// 无调用者,this指向window
 var name = "window"
    function a (){
        var name ="cherry"
        console.log(name) // cherry
        console.log(this.name) // window
    }
  	a(); 
    // 有调用者,this指向调用者
    var name = "windowName"
    var a = {
        name:'cherry',
        fn:function(){
            console.log(this.name) // cherry   this指向a(调用者)
        }
    }
    a.fn()
    
    // 指针指向最后的调用者
    var name = "windowName"
    var a = {
        name:'cherry',
        fn:function(){
            console.log(this.name) // cherry
        }
    }
    window.a.fn() // 最后的调用者是a
    //
    var name = "windowName"
    var a = {
        fn:function(){
            console.log(this.name) // undefined,调用者a中没有给name赋值
        }
    }
    window.a.fn()
    // 将函数赋值给变量
    var name = "windowName"
    var a = {
        name: 'cherry',
        fn:function(){
            console.log(this.name) // windowName
        }
    }
    // a.fn()
    var f = a.fn // 把函数赋值给变量,函数并没有执行
    f() // 变量执行没有调用者
    //
    var name = "windowName"
    function fn(){
        var name ="cherry";
        innerFun() // 无调用者
        function innerFun(){
            console.log(this.name) // windowName
        }
    }
    fn() // 无调用者

指针指向调用者

2.如何改变指针

var name = "windowName"
var a = {
    name:'cherry',
    func1: function(){
        console.log(this.name)
    },
    func2:function(){
        setTimeout(function(){
            console.log(this) // window,没有调用者
            this.func1() // 这里的this指向window,所以报错
        },100)
    }
}
a.func2()

若要让上述代码执行,就得改变this的指向

  • 改变方法一:箭头函数(静态绑定,它会捕获其所在(即定义的位置)上下文的this值, 作为自己的this值)
 func2:function(){
        setTimeout(()=>{
            console.log(this) // a
            this.func1()
        },100)
    }

  • 改变方法二:声明变量保存(闭包)
 func2:function(){
        var _this = this;
        setTimeout(function(){
            console.log(_this) // a
            _this.func1()
        },100)
    }
  • 改变方法三:call()和apply()动态改变 call用来执行一个函数,用“函数名.call(作用域对象)”,将函数放到特定的作用域来执行
 func2:function(){
        setTimeout(function(){
            console.log(this) //a
            this.func1()
        }.call(a),100)
    }

apply用来执行一个函数,用“函数名.apply(作用域对象)”,将函数放到特定的作用域来执行

 func2:function(){
        setTimeout(function(){
            console.log(this) //a
            this.func1()
        }.apply(a),100)
    }

call()和apply()的区别:参数不一样

var a = {
    name:'cherry',
    fn: function(a,b){
        console.log(a+b)
    }
}
var b = a.fn;
b.apply(a,[3,5])
b.call(a,3,2)
b.call(a,3,2)
var c = b.bind(a,12,2) //绑定作用域,给c绑定作用域a
c() // 执行c的时候,c的作用域是a

apply(对象,数组)

calll(对象,多个参数用逗号隔开)

bind(对象,多个参数用逗号隔开):用于绑定作用域,不立即执行

3.

call()的实现原理