JavaScript——this

99 阅读5分钟

概述

this 是JavaScript中的一个关键字,它是函数运行时,在函数体内自动生成的一个对象,只能函数体内部使用。

this就是指针 ,指向调用函数的对象这个对象我们称为函数执行的上下文对象

全局上下文(在所有函数外面)this指的是全局对象 window,

函数上下文(在某个函数的内部)this指的是当前函数所属的对象。

就是谁调用就指向谁。


调用方式

  1. 全局环境中this指向全局变量(window)
console.log(this);//window
  1. 函数中的this,由调用函数的方式来决定
  • 如果函数是独立调用的,在严格模式(use strict)下是指向undefined的
"use strict";
function f(){
    console.log(this);//undefined
  }
f()

在非严格模式下,指向window

var name="全局";

function a(){
  var name="函数内部";
  console.log(this.name)//全局
  console.log(this)//window
}
a()
  • 如果这个函数是被某一个对象调用,那么this指向被调用的对象
let  obj={
  name:"obj的name",
  
  fn:function(){
  clg(this.name)//obj的name
}
  
}
obj.fn();
  1. 构造函数与原型里面的this

构造函数里的this以及原型里的this对象指的都是生成的实例。(由new决定)

通过new操作符可以初始化一个constructor的指向,new的作用域就是创建一个对象的实例,constructor也就是指向了一个新的执行环境“在这个对象之中”。

  1. 箭头函数

箭头函数按词法作用域来绑定它的上下文,所以this 实际上会引用到原来的上下文。

(箭头函数会保持它当前执行上下文的词法作用域不变,而普通函数则不会,箭头函数从包含它的词法作用域中 继承了this的值)。

箭头函数没有自己的this,指向外层作用域

var obj = {
  foo() {
    console.log(this);
  },
  bar: () => {
    console.log(this);
  }
}

obj.foo() // {foo: ƒ, bar: ƒ}  指向obj
obj.bar() // window

其他情况

全局下把对象赋值给变量时

把对象赋值给一个变量,调用该方法时,this 指向window

 var name="全局name";

 var obj= {
    name:"obj的name",
    fn:function(){
        console.log(this.name); //全局name
    }
}
//把对象赋值给一个变量
var test=obj.fn;
test()

个人理解:test全局下调用

包含多个对象,只指向上一级

var obj={
  a:10,
  b:{
    a:12,
    fn:function(){
      console.log(this.a)
    }
  }
}
obj.b.fn()//12

this指向的是对象b

如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象。


看下一个例子

var o = {
    a:10,
    b:{
        fn:function(){
            console.log(this.a); //undefined
        }
    }
}
o.b.fn();

尽管对象b中没有属性a,这个this指向的也是对象b,因为this只会指向它的上一级对象,不管这个对象中有没有this要的东西。

var o = {
    a:10,
    b:{
        a:12,
        fn:function(){
            console.log(this.a); //undefined
            console.log(this); //window
        }
    }
}
var j = o.b.fn;
j();

这里this指向的是window

j 在全局下调用

总结

this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的。

在js的严格模式中this指向的不是window


自执行函数

自执行函数的this指向window

 var obj = {
            foo: "test",
            fn: function () {
                var mine = this;//这个this是指向obj的,可以clg一下
                console.log(this.foo);   //test
                console.log(mine.foo);   //test

                (function () {
                    console.log(this);//window
                    console.log(this.foo); //undefined
                    console.log(mine.foo); //test
                    console.log(mine);//object
                })();
            }
        };
        obj.fn();

测试一下有没有掌握

1

var a=1;

var obj={
  b:function(){
    console.log(a)
    console.log(this.a)
  }
}
obj.b()

1

undefined

2

var a=1;
var obj={
  a:"obj里面的a",
  b:function(){
    console.log(a)
    console.log(this.a)
  }
}
obj.b()

1

obj里面的a

var a=1;
var obj={
  a:"obj里面的a",
  b:function(){
    var a="bbb"
    console.log(a)//bbb
    console.log(this.a)
  }
}
obj.b()

3

var a=1;
var obj={
  a:"obj里面的a",
  b:function(){
    var t=this
    console.log(a)
    console.log(this.a)
    console.log(t.a)
    console.log(t)
  }
}
obj.b()

1

obj里面的a

obj里面的a

{a: 'obj里面的a', b: ƒ}

4

 var obj = {
            a: 10,
            b: this.a + 10, 
            //这里的this指向window(全局),a为undefined  ==>  undefined + 10 = NaN
            fn: function () {
                return this.a;
            }
        }
        console.log(obj.b)
        console.log(obj.fn())

NaN

10

5

var obj= {
    user:"o的user",
    fn:function(){
        console.log(this.user);  //o的user
    }
}
var test=obj.fn;
test()//undefined

赋值给一个变量,最后指向全局

6

var obj={
  a:10,
  b:{
    a:12,
    fn:function(){
      console.log(this.a)
    }
  }
}
obj.b.fn()

指向上一级 输出12

7

var o = {
    a:10,
    b:{
        fn:function(){
            console.log(this.a); //undefined
        }
    }
}
o.b.fn();

输出undefined,指向上一级

8

var o = {
    a:10,
    b:{
        a:12,
        fn:function(){
            console.log(this.a); //undefined
            console.log(this); //window
        }
    }
}
var j = o.b.fn;
j();

最后是 j 调用的,指向window

9

               function fn( ) {
               'use strict';
                var a = 1;
                var obj = {
                    a: 10,
                    c: this.a + 20   
                  //严格模式下,a指向undefined嘛,undefined.a报错
                }
                return obj.c;
              }
             console.log(fn());       //输出报错

严格模式下 this 指向 undefined

10

 var obj = {
            foo: "test",
            fn: function () {
                var mine = this;//这个this是指向obj的,可以clg一下
                console.log(this.foo);       //test
                console.log(mine.foo);       //test

                (function () {
                    console.log(this.foo);    //undefined
                    console.log(mine.foo);    //test
                    console.log(this);//window
                    console.log(mine);//object
                })();
            }
        };
        obj.fn();

外部的函数this指向obj,内部的 自执行函数的 this 指向window

11

            var a = 20; 
            var obj = {
                a: 10,
                getA: function () {
                    return this.a;
                  }
            }
            console.log(obj.getA());    //10
            var test = obj.getA;
            console.log(test());        //20   独立调用test

12

             var a = 5;

             function fn1(){
                 var a = 6;
                 console.log(a);        //6
                 console.log(this.a);   //5
             }  
             function fn2(fn) {
                 var a = 7;
                 fn();
            } 
             var obj = {
                 a: 8,
                 getA: fn1
             }  
            fn2(obj.getA); 
            obj.getA();//6  8

13

               function fn( ) {
               'use strict';
                var a = 1;
                var obj = {
                    a: 10,
                    c: this.a + 20        //严格模式下,a指向undefined嘛,undefined.a报错
                }
                return obj.c;
              }
             console.log(fn());       //输出报错==》 a undefined

14

           // 声明一个构造函数 
             function Person(name, age) {
                this.name = name;
                this.age = age;
                console.log(this);      //与下面的this是一样的,都是Person
            }   
            // Person();           //this 指向window
            Person.prototype.getName = function () {
                console.log(this);      //与上面的this是一样,都是Person
            }; 
            var p1 = new Person("test", 18);
            p1.getName();

15

             var obj = {
               foo: "test",
               fn: function(){
                   var mine = this;
                   console.log(this.foo);       //test
                   console.log(mine.foo);       //test
                   
                   (function(){
                      console.log(this.foo);    //undefined
                      console.log(mine.foo);    //test
                   })();  
               } 
            };
            obj.fn();
 
/**
 (1) 在外部函数中, this 和 mine两者都指向了obj,因此两者都可以正确地引用访问foo;
(2)在内部函数中,this不再指向obj,this.foo 没有在内部函数中被定义,
    而指向到本地的变量mine保持在范围内,并且可以访问
    (在ES5之前,内部函数的this将指向全局的
    window对象; 则作为ES5,内部函数中的this是未定义的。)
            
            */

16

           function foo(){
                console.log(this.a);
            }
            var a = 2;
            var o = {
                a:3, 
                foo: foo
            };
            var p = { a:4 };
            o.foo();  //3
            (p.foo = o.foo)();      //2
            /**
                相当于: 
                function w(){
                    p.foo = o.foo;
                }
                w();
                此时的constructor指向window,调用这个w,这个w是在window下创建的,相当于
                调用window.w(),所以constructor指向window。
            */
 
            p.foo = o.foo;
            p.foo();    //4     函数由p执行,那么constructor指向的就是对象p,谁调用就指向谁0.0
            //this也就指向p, 因此this.a === p.a