JavaScript中的this对象

首先要搞懂一个问题,函数中的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

    原文作者:岛在深海处
    原文地址: https://www.jianshu.com/p/5be91fb35301
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞