JS中this指向问题

与其它语言相比,JS的this关键字的指向稍微有点差别。
一、全局环境
首选我们要明确一点,在全局环境中(在任意函数体外部),无论是严格模式还是非严格模式,this都指向window。下面,我们来通过几个例子理解一下。

        //示例1
        console.log(this)//这里的this在全局域下,指向window

        //示例二
        var a = 10;
        var obj = {
            a : 12,
            b : this.a //这里的this在全局域下,指向window
        }
        console.log(obj.b) //返回10

二、函数环境
函数在未执行时,函数内部this指向undefined,函数被调用后,this指向取决于被调用的方式。同样的我们来通过几个例子来理解一下。

  // 示例一
        var a = 10;
        function fun1(){
            var a = 12;
            console.log(this.a);//打印10 
            function fun2(){
                console.log(this.a);//打印10 
            }
            fun2();//这相当于 window.fun2() 在window 中调用fun1,this 指向window
        }
        fun1();//这相当于 window.fun1() 在window 中调用fun1,this 指向window

        //示例二
        var b = 10;
        var obj = {
            b : 12,
            fun1 : function(){
                console.log(this.b)//打印 12 打印10 打印12
                return function fun(){
                    console.log(this.b) // 打印10
                }
            },
            c : {
                b : 14,
                fun2 : function(){
                    console.log(this.b) //打印14
                }
            }
        }
        obj.fun1()//在obj 中调用fun1,this 指向obj 所以会打印 12
        obj.c.fun2()//在c 中调用fun2,this 指向c 所以会打印 14
        var res1 = obj.fun1 //将fun1赋给res1
        res1() //这相当于 window.fun1() 在window 中调用fun1,this 指向window,所以打印10
        var res2 = obj.fun1() //执行fun1中打印12,然后将fun1函数执行的返回值赋给res2,也就是将fun的函数体赋给res2
        res2()//这相当于 window.fun() 在window 中调用fun,this 指向window,所以打印10

以上是我们常见的函数执行时的this 问题,当然除了以上这些基本问题之外,还会遇到立即执行函数,箭头函数,事件处理函数,构造函数的this指向问题,下面来介绍一下这些函数中的this指向问题。
1.立即执行函数中的this
立即执行函数中的this指向全局,也不难理解,立即执行函数在定义时即被执行,相当于在window下执行该函数。`

        var num = 3;
        var obj = {
            num: 5,
            fun: (function () {
                var num = 4;
                console.log(this.num) //this 执行window 打印3
            })()
        }

2.箭头函数
箭头函数的this指向和其上一层作用域的this指向一致。

        var name = 'sun';
        var obj = {
            name: 'cat',
            say: () => {
                console.log(this.name);//打印sun
            }, 
            fun: function () {
                console.log(this.name);//打印cat
            }
        };
        obj.say();//say是箭头处理函数,this和上一层环境一致,上一层是全局环境,this指向window,所以打印sun
        obj.fun();//fun是普通函数,谁调用指向谁,所以this指向obj,打印cat

3.在事件处理函数中,哪个元素触发事件,this就指向哪个元素

        //获取 Id = Btn 的标签
        var btn = document.getElementById('Btn');
        //在事件处理函数中,哪个元素触发事件,this指向哪个元素
        btn.onclick = function(){
            console.log('点击了')
            console.log(this) //this指向btn
            this.style.color = 'red'          
        }

4.构造函数
在正常的构造函数中,构造函数中的this指向实例化对象。

        function Person(){
            this.name = 'cat',
            this.age = 21,
            this.friend = 'sun'
        }
        var person1 = new Person()
        console.log(person1) // Person {name: "cat", age: 21, friend: "sun"}
        function Person(){
            this.name = 'cat',
            this.age = 21,
            this.friend = 'sun'
        }
        var person1 = new Person() //这里的构造函数中的this指向person1
        console.log(person1) // Person {name: "cat", age: 21, friend: "sun"}
        person1.hobby = 'game'//给person1添加属性,不影响原构造函数
        console.log(person1) // Person {name: "cat", age: 21, friend: "sun", hobby: "game"}
        var person2 = new Person() //这里的构造函数中的this指向person1
        console.log(person2) // Person {name: "cat", age: 21, friend: "sun"}

当然,我们也可以手动破坏构造函数,当在构造函数中返回数组,对象,函数时,构造函数的this指向将会指向返回的数组,函数,函数。

        //正常环境
        function Person(){
             this.name = 'cat'
        }
        var person = new Person();
        console.log(person.name) //打印cat

        //返回数组
        function Person(){
             this.name = 'cat'
             return []
        }
        var person = new Person();
        console.log(person)//打印 []
        console.log(person.name) //打印undefined

         //返回对象
         function Person(){
             this.name = 'cat'
             return {}
        }
        var person = new Person();
        console.log(person)//打印 {}
        console.log(person.name) //打印undefined

         //返回函数
         function Person(){
             this.name = 'cat'
             return function fun(){}
        }
        var person = new Person();
        console.log(person)//打印 ƒ fun(){}
        console.log(person.name) //打印undefined

讲到这里,我们会发现this指向在使用时我们很难把控,那有没有方法将this指向我们自己所希望指向的对象呢?答案是肯定的。
三、this的显式函数绑定
我们可以通过call,apply,bind进行显式函数绑定。

        var obj1 = {
            name : 'cat',
            say : function fun(){
                console.log(this.name)
            }
        }
        var obj2 = {
            name : 'sun',
            say : function fun(){
                console.log(this.name)
            }
        }
        obj1.say() // 函数的普通调用,谁调用this 指向谁,所以打印cat
        obj1.say.call(obj2)//call强制改变obj1中this指向,并且规定指向obj2,所以打印sun
        obj1.say.apply(obj2)//apply强制改变obj1中this指向,并且规定指向obj2,所以打印sun
        var res = obj1.say.bind(obj2)//bind强制改变obj1中this指向,并且规定指向obj2,同时返回say函数体
        res()//即使res是在全局环境调用,但是this依旧指向obj2,打印sun
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值