zoukankan      html  css  js  c++  java
  • this的指向问题

    原答案地址:https://zhuanlan.zhihu.com/p/23804247

    最开始,先看一下,为什么这里的this输出结果并不一样?

    var obj = {
        foo: function (){
            console.log("this-->>", this)
        }
    }
    
    var bar = obj.foo
    obj.foo() //打印出来的this是obj
    bar() //打印出来的this是window

    一、函数调用

    1、首先要从函数的调用讲起,JS里面有三种函数调用形式:

    func(p1,p2)
    obj.child.method(p1, p2)
    func.call(context, p1, p2)

    一般,我们知道前两种,并且认为前两种是优先于地上那种的。但实际上,第三种调用方式,才是正常的调用形式。

    func.call(context, p1, p2)

    其他两种方式是语法糖,可以等价地变换为call的形式。

    func(p1, p2) //等价于
    func.call(undefined, p1,p2)
    
    obj.child.method(p1, p2) //等价于
    obj.child.method.call(obj.child, p1, p2)

    因此,我们的函数调用只有一种形式:

    func.call(context, p1, p2)

    这样,this就好解释了:

    this,就是上面的context。

    this是你call一个函数时传的context, 由于你从来不用call形式的函数调用,所以你一直不知道。

    先看func(p1, p2)里的this是如何确定的:

    function func(){
        console.log(this)
    }
    func() 
    //等价于
    function func(){
        console.log(this)
    }
    func.call(undefined)

    按道理来说,打印出来的this应该是undefined,但是浏览器有一条规则:

    如果你传的context是null或者undefined,那么window对象就是默认的context(严格模式下默认context是undefined),因此,上面打印的结果是window。

    如果你希望this不是window,很简单:

    func.call(obj) //这里的this就会是obj对象了

    2、再来看obj.child.method(p1, p2)里的this是如何确定指向的:

    var obj = {
        foo: function(){
            console.log(this)
        }
    }
    obj.foo()
    //等价于 obj.foo.call(obj)

    因此,this就是obj。

    回到最开始的问题,obj.foo(),可以转化为obj.foo.call(obj), 因此,this就是obj。

    bar()可以转化为 bar.call(), 由于没有传context,所以this就是undefined,根据浏览器默认原则,this指向的window。

    二、 []语法

    function fn(){console.log(this)}
    function fn2(){console.log("this-->>", this)}
    var arr = [fn, fn2]
    arr[0]()

    想一下,arr[0]()这里的this指的是什么?

    我们可以将arr[0]()想成arr.0(),虽然后者的语法错了,但是形式与转换代码里面的obj.child.method(p1, p2)对应上了,于是:

    arr[0]()可以转化为:arr.0(),接着转化为arr.0.call(arr), 那么,this值得就是arr了。

    三、箭头函数

    如果你在箭头函数里看到this,直接把他当做箭头函数外面this即可。外面的this是什么,箭头函数里面的this就还是什么,因为箭头函数本身不支持this。

    四、总结

    1、this就是当你call一个函数的时候,传入的第一个参数。this就是call的第一个参数。

    2、如果你的函数调用形式不是call形式,可以按照“转化代码”转换为call形式。

  • 相关阅读:
    Java速成笔记
    C语言学习笔记
    形式语义05 Semantics
    密码学04 PRG&PRF
    形式语义04 Types
    密码学03 Computational
    形式语义03 Lambda
    密码学02 Perfect
    形式语义01 Intro
    密码学01 Intro
  • 原文地址:https://www.cnblogs.com/qingshanyici/p/14284208.html
Copyright © 2011-2022 走看看