美文网首页JavaScript 进阶营
JavaScript中的this对象

JavaScript中的this对象

作者: 岛在深海处 | 来源:发表于2018-08-19 00:40 被阅读0次
    首先要搞懂一个问题,函数中的this到底是怎么来的?

    普通函数参数列表中有一个默认参数self,这个self的值就是根据该函数被调用时所处的上下文来定的,需要说明的一点是,变量存储的都是地址:
    每个function(){}都是独立存在的,就算赋值给一个变量a,该变量a也只是持有该函数的地址,这时候如果再将该变量a赋值给变量b,这时候b就直接持有function(){}的地址,调用b()时候就触发了函数的执行,这时候就会传入上下文当第一个参数(隐藏),所以最终传进去的self的值就是该函数执行环境的上下文。

    var obj = {
      a: function () { console.log(this.bar) },
      bar: 1
    };
    
    var b = obj.a;
    var bar = 2;
    //在obj对象内执行,上下文为obj对象。
    obj.a() // 1
    //上下文为window对象。
    b() // 2
    

    注意:箭头函数没有默认参数self,运行的时候也就不会有上下文传进去。

    搞懂了this是怎么来的,我们再来看问题:函数被调用时,函数内的this指向哪个对象?

    我们把函数分为普通函数与箭头函数2种

    • 普通函数下:
      1.this总是指向它的直接调用者(使用时所在的上下文)。
      例如:obj.func ,那么func中的this就是obj,在window中直接调用func(),那么func中的this就是window

    • 箭头函数下
      1.箭头函数的this对象,就是定义时所在的上下文(即定义时的上层函数内的this),而不是使用时所在的上下文。

    因为箭头函数没有默认参数self,所以箭头函数内的this在定义的时候就已经被赋值了this = 定义时所在上下文。

    下面举个例子验证下:

    let  obj={
        foo:()=>{
            console.log(this) //1. window
            return () => {
                console.log(this) //2. window
                return function(){
                    console.log(this) //3. 定义时所在的上下文,这里指上层函数的this
                    return () => {
                        console.log(this) //4. 定义时所在的上下文,这里指上层函数的this
                    }
                }
            };
        }
    }
    
    //这种情况第四个this都指向window,因为调用它的对象为window
    var b = obj.foo().call({name: 'chenyou'})() ()
    
    //这种情况第三个this指向{name: 'chenyou'},因为调用它的是这个对象
    //第四个this也指向{name: 'chenyou'},因为它定义在第三个方法内,而第三个方法内的this指向{name: 'chenyou'}
    var b = obj.foo()().call({name: 'chenyou'})()
    

    思考:第一个箭头函数是定义在obj对象中的,根据定义应该指向obj对象才对,为什么第一个箭头函数的this指向了window呢?

    要回答这个问题就涉及到Window的原理了,Window就是一个函数,在控制台打印Window :
    ƒ Window() { [native code] }
    再打印Window的实例window:
    一堆可供调用的方法...
    __ proto__:Window
    看到这里我们发现window对象与我们的普通对象基本无区别,

    既然这样我们就自己造一个假Window放在真Window中:

    function myWindow(){
        this.test = {
            getThis: this //该this指向myWindow中的上下文this
        }
    
        this.test.obj = {
            name: 'chenyou',
            getThis:this,
            foo: () => {
                console.log(this)
            }
        }
        this.test.obj.foo() //this指向myWindow中的this
    }
    var myw = new myWindow()
    myw.test.getThis  // myWindow
    

    可以看到普通对象中的this确实是指向的外层function(){}中的上下文。
    箭头函数中的this指向了myWindow中的上下文(this),而这个上下文取决于调用myWindow这个函数传进来的self参数。
    从上面这两个举例我们暂时得出结论(经过实验证明结论是正确的):

    结论1:只要箭头函数定义的地方的外层有普通函数,不管嵌套了几层普通对象,箭头函数中的this都是指向最近外层的普通函数中的this.

    突然想到new一个对象,给对象赋值箭头函数,看看箭头函数中的this指向谁

    var myclass = function () {
        this.name = 'chenyou'
        this.foo = () => {
            console.log(this)
        }
    }
    
    myclass.prototype.pfoo = function(){
        console.log(this)
    }
    myclass.prototype.pjfoo = () => {
        console.log(this)
    }
    
    var myc = new myclass()
    myc.foo() // myclass
    myc.pfoo() //myclass
    myc.pjfoo () //Window
    
    myc.foo2 = () => {
        console.log(this)
    }
    myc.foo3 = function(){
      console.log(this)
    }
    
    myc.foo2() // Window
    myc.foo3.call({name:"hhh"})
    

    foo()箭头函数因为是定义在myclass函数中的,所以this指向myclass的实例
    pfoo()普通函数因为是在Window下调用,所以this指向Window
    pjfoo()、foo2()箭头函数因为是在Window下定义,所以this指向Window
    foo3()普通函数因为调用它的对象是{name:"hhh"},所以指向{name:"hhh"}对象

    这里foo与foo2中的this不同是因为它们之间隔了个new。

    结论2:箭头函数在哪定义,不管赋值给了哪个对象的变量,不管嵌套了几层普通对象,this都指向都是它最近外层函数中的this

    相关文章

      网友评论

        本文标题:JavaScript中的this对象

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