美文网首页
this指向、call、apply、bind

this指向、call、apply、bind

作者: 无穷369 | 来源:发表于2021-03-07 14:17 被阅读0次

    思考下面这几种情况下输出的结果,来理解this的指向问题

    var name = 'windowName'
    function a(){
        var name = 'zhangsan'
        console.log(this.name)
    }
    a()
    

    解释:
    this 指向的是调用他的对象,上面的 a() 是没有调用者的,所以 this 指向的是默认的 windowvar name = 'windowName' 就是先把 name 属性挂到 window 上,然后再赋值为 windowName

    var name = 'windowName'
    var a = {
        name: 'zhangsan',
        fn: function(){
            console.log(this.name)
        }
    }
    a.fn()
    

    解释:
    fn() 的调用者是 a ,所以 this 指向 athis.name 也就是 a.name

    var name = 'windowName'
    var a = {
        name: 'zhangsan',
        fn: function(){
            console.log(this.name)
        }
    }
    var f = a.fn
    f()
    

    解释:
    fn() 没有调用者,所以 this 指向的是默认的 window ,所以打印的是 windowName

    var name = 'windowName'
    function fn(){
        var name = 'zhangsan'
        innerFun()
        function innerFun(){
            console.log(this.name)
        }
    }
    fn()
    

    解析:
    同理,fn() 并没有调用者,所以 this 指向的还是 window

    var name = 'windowName'
    var a = {
        name: 'zhangsan',
        func1: function(){
            console.log(this.name)
        },
        func2: function(){
            setTimeout(function(){
                this.func1()
            },100)
        }
    }
    a.func2()
    

    解析:
    在这里,setTimeout 中的 this 没有调用者,所以指向的是 window ,所以结果是 undefined

    那如何才能使这里的 setTimeout 中的这个 this 指向 a 对象呢?

    1. 可以使用箭头函数
    setTimeout(() => {
      this.func1()
    },100)
    
    1. 可以用一个变量存储指针
    var that = this
    setTimeout(function(){
      that.func1()
    },100)
    
    1. 使用 函数.call(作用域对象)
    setTimeout(function(){
      this.func1()
    }.call(a),100)
    
    1. 使用函数.apply(作用域对象)
    setTimeout(function(){
      this.func1()
    }.apply(a),100)
    

    可以看到 callapply 都可以改变 this 的指向,但是他们有什么区别呢?

    var a = {
        name: 'zhangsan',
        fn: function(a,b){
            console.log(a + b)
        }
    }
    var b = a.fn
    // 多个参数是用数组的形式传递
    b.apply(a, [1,2])
    // 多个参数直接在后面追加传递
    a.call(a,1,2)
    
    1. 使用 bind 绑定作用域,但不立即执行,需要手动再执行
    setTimeout(function(){
      this.func1()
    }.bind(a)(),100)
    

    call的实现原理

    Function.prototype.mycall = function(ctx){
        ctx = ctx || window
        ctx.fn =  this // 这个this就是调用者对象
        let arg = [...arguments].slice(1)
        let result = ctx.fn(...arg)
        return result
    }
    

    相关文章

      网友评论

          本文标题:this指向、call、apply、bind

          本文链接:https://www.haomeiwen.com/subject/eyneqltx.html