判断this指向问题

298 阅读3分钟

如何判断this指向

口诀:一般来说就是谁调用它,this就指向谁

1.普通函数(this指向window)

        var age=18;
        function fn(){
            console.log(this);
        }
        fn()//Window {window: Window, self: Window, document: document, name: '', location: Location, …}

按照口诀fn()等于window.fn(),所以this指向window

2.箭头函数

        var age=19;
        var arrow=()=>{
            var age=20;
            console.log(this.age);
        }
        arrow()//19

箭头函数的this取决于其父级作用域,没有的话就是全局也就是window

3.对象函数(this指向该方法所属对象)

一层对象中的普通函数

        var name='张三'
        var obj={
            name:"李四",
            say:function (){
                console.log(this.name);
            }
        }
        obj.say()//李四
        /************************/
        

一层对象中的普通函数,obj调用了say(),所以this指向了obj

一层对象中的箭头函数

        var name='张三'
        var obj={
            name:"李四",
            say:()=>{
                console.log(this.name);
            }
        }
        obj.say()//张三

一层对象中的箭头函数,箭头函数的this指向取决于父级作用域,父级这里是对象,对象没有作用域且现在是位于全局,所以继续向上找,找到全局

两层对象中的普通函数

        var name='张三'
        var obj={
            name:"李四",
            say:function (){
                console.log(this.name);
            },
            secondObj:{
                name:"王五",
                say:function (){
                    console.log(this.name);
                }
            }
        }
        obj.say();//李四
        obj.secondObj.say()//王五

和一层的普通函数一样谁调用就指向谁

两层对象中的箭头函数

        var name = '张三'
        var obj = {
            name: "李四",
            say: () => {
                console.log(this.name);
            },
            secondObj: {
                name: "王五",
                say: () => {
                    console.log(this.name);
                }
            }
        }
        obj.say();//张三
        obj.secondObj.say()//张三

同理和一次函数对象的箭头函数相同,箭头函数的this取决于父级作用域,父级是对象没有继续往上延升,最后就找到了全局

对象里的方法返回普通方法

        var age=18;
        var obj={
            age:"19",
            say:function (){
                return function (){
                    console.log(this.age);
                }
            }
        }
        obj.say()//ƒ (){console.log(this.age);}
        obj.say()();//18

obj.say()执行后返回一个方法,所以再加一个()会执行,执行的时候这个方法相当于被全局调用,所以这个this指向全局。但本质上从对象中返回方法,目的就是使用对象中的属性。

        var age=18;
        var obj={
            age:"19",
            say:function (){
                var that=this
                return function (){
                    console.log(that.age);
                }
            }
        }
        obj.say()//ƒ (){console.log(that.age);}
        obj.say()();//19

在函数返回之前,我们通过that获取到指向obj的这个this,所以结果是这里的19

对象里的方法返回箭头方法

        var age=18;
        var obj={
            age:"19",
            say:function (){
                return  ()=>{
                    console.log(this.age);
                }
            }
        }
        obj.say()//ƒ (){console.log(this.age);}
        obj.say()();//19

箭头函数的this指向父级作用域,这里箭头函数的父级是function,function会形成作用域,这里function作用域中的this指向obj,所以箭头函数指向了obj

4.构造函数

普通构造函数

        function Person(name,age){
            this.name=name;
            this.age=age
        }
        var zs=new Person('张三',18)
        console.log(zs);//Person {name: '张三', age: 18}
        
        /*********************/
        function Person(name,age){
            this.name=name;
            this.age=age;
            var obj={
                age:10
            }
            return obj
        }
        var zs=new Person('张三',18)
        console.log(zs);//{age: 10}

构造函数在没有return的情况下,this指向实例化的对象,有return,则指向返回的那个对象

构造函数里的方法

        var name = '张三'
        function Person() {
            this.name = '李四';

            this.commonFn = function () {
                console.log(this);
            }
            this.arrowFn = () => {
                console.log(this);
            }
        }
        var number = new Person()
        number.commonFn();//Person {name: '李四', commonFn: ƒ, arrowFn: ƒ}
        number.arrowFn()//Person {name: '李四', commonFn: ƒ, arrowFn: ƒ}

构造函数里的普通方法this指向构造函数new后的实例,箭头函数还是寻找父级作用域,父级是Person(),方法是有自己的作用域的,所以箭头函数指向Person