解析器在调用函数时每次都会向函数内部传递进一个隐含的参数

  • 这个隐含的参数就是 this ,this 指向的是一个对象,
  • 这个对象我们称为函数执行的上下文对象,

    this 的由来

    javascript 允许在函数体内,引用当前环境的其它变量
    1. var fun = function(){
    2. console.log(x);
    3. }

    上面代码使用变量x,而变量x由当前的运行环境提供。
    那么问题来了,函数可以在不同的运行环境下执行,所以需要一种机制,可以在函数体内内部获取当前的运行环境(context),所以this就出现了,它的作用就是在函数体内部,指代当前的运行环境。

根据函数的调用方式的不同,this 会指向不同的对象

  • this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁,

    以函数的形式调用时,this 永远都是 全局对象 window

    1. //定义一个全局变量age
    2. var age=18;
    3. //声明一个全局函数getAge
    4. function getAge(){
    5. return this.age;
    6. }
    7. //因为是全局环境内调用的getAget函数所以指向的对象为window
    8. console.log(getAge());//18
    9. //你也可以这样写
    10. console.log(window.getAge());//18
    以上代码中,getAge方法在全局window下调用,所以getAge方法内的this指向的是window。为了更好的验证这一点,咱们再来对以上代码修改如下:
    1. //声明一个全局函数getAge
    2. function getAge(){
    3. //由于该函数在全局环境(window)下调用,所以this为window
    4. this.age=81;//为this指向的window对象添加属性age
    5. }
    6. getAge();//全局调用函数getAge()
    7. console.log(age);//81
    8. //也可以这样输出
    9. console.log(window.age);//81
    以上代码中声明了一个全局函数getAge。由于该函数在全局环境(window)下调用,所以this为window。然后通过this.age为window对象增加一个age属性。所以在调用完该函数后进行console.log(window.age)输出的结果为81。

以方法的形式调用时,this 就是调用方法的那个对象

  1. var name = "哈哈";
  2. var obj = {
  3. name:"嘿嘿",
  4. getName:function(){
  5. return this.name;
  6. }
  7. }
  8. console.log(obj.getName()); // 嘿嘿
  1. var obj={
  2. //obj属性age
  3. age:12,
  4. //obj方法getAge
  5. getAge:function(){
  6. return this.age;
  7. }
  8. }
  9. //全局属性age
  10. var age=13;
  11. //全局方法getAge
  12. function getAge(){
  13. return this.age;
  14. }
  15. //在全局环境下,this代表window,所以下面可以理解为window对象下调用全局getAge
  16. console.log(this.getAge());//13

在全局环境下,this代表的是window。所以调取的方法为全局方法getAge。又因为getAge是在window下调用的,所以内部this指向的是window对象。最终输出结果为13。

接下来看种丢失掉this的情况,换言之,this的指向发生改变。我们先来看下面的代码

var obj={
    //obj属性age
    age:12,
    //obj方法getAge
    getAge:function(){
        return this.age;
    }
}
//全局属性age
var age=13;
//全局方法getAge
function getAge(){
    return this.age;
}
//在obj对象下调用getAge(),this代表的是obj
console.log(obj.getAge());//12
//将obj下的函数getAge赋值给fn。
var fn=obj.getAge;
//在全局环境(window) 下调用fn,this代表的是window
console.log(fn());//13

当调用obj.getAge时,getAge方法是作为obj对象的属性来调用的。输出结果为12。当将obj.getAge赋值给一个变量fn时,因为fn的调用是在全局环境下调用的,所以this指向的是window,输出结果为13。

将代码汇总如下,认真看看:

var obj={
    //obj属性age
    age:12,
    //obj方法getAge
    getAge:function(){
        return this.age;
    }
}
//全局属性age
var age=13;
//全局方法getAge
function getAge(){
    return this.age;
}
//在obj对象下调用getAge(),this代表的是obj
console.log(obj.getAge());//12
//在全局环境下,this代表window,所以下面可以理解为window对象下调用全局getAge
console.log(this.getAge());//13
//将obj下的函数getAge赋值给fn。
var fn=obj.getAge;
//在全局环境(window) 下调用fn,this代表的是window
console.log(fn());//13

参考链接:https://zhuanlan.zhihu.com/p/264423222