美文网首页
JavaScript中this的指向

JavaScript中this的指向

作者: 变量只提升声明不提升赋值 | 来源:发表于2020-12-22 17:55 被阅读0次

    this常见的4中指向
    1.在浏览器中

    <script type="text/javascript">
        /**
         * 1.this默认指向当前window,在函数中也是指向当前window。
              而全局变量,也会变成当前window对象的一个属性。
         */
        var num = 4
        console.log(this)
        console.log(this.num)
         function f() {
             console.log(this)
             console.log(this.num)
         }
         f()
    </script>
    
    image.png

    可以看到,打印出来的this指向的都是window对象,在函数中也是如此
    2.在元素的监听事件中

    <style>
        .div1 {
            width: 100px;
            height: 100px;
            background-color: red;
        }
    
        .div2 {
            width: 50px;
            height: 50px;
            background-color: yellow;
        }
    </style>
    <body>
    <div class="div1">
        <div class="div2"></div>
    </div>
    <script type="text/javascript">
        /**
         * 2.在事件侦听中,this指向侦听的那个元素本身,
         */
        console.log(document.getElementsByClassName('div2'))
        document.getElementsByClassName('div1')[0].onclick = function (e) {
            console.log(this)
            console.log(e.target) //target指触发这个事件的元素
            console.log(e.currentTarget) //currentTarget指事件侦听的这个元素
        }
    </script>
    

    这里我们有两个div,一个大的div1包着一个小的div2,我们给这个div1绑定一个点击侦听,并且在里面去打印这个this。


    image.png

    可以看到这里的this指向了div1这个元素,在研究this的时候我还惊奇的发现,e.target和e.currentTarget有点细微的区别。
    上图的打印是点击小黄块触发的,也就是点击div2触发的,这个时候可以看到this指向的是div1,e.target是div2,e.currentTarget还是div1。接下来我们点击大红块看看会发生什么


    image.png

    点击红快快的时候看到e.target也变成了div1,所以这个时候得出,e.target指的是触发这个侦听事件的元素,就是你点的那个元素。e.currentTarget则是绑定侦听事件的元素,和this一样。他们俩是不变的,哪个元素绑定了点击侦听,他们俩就指向谁

    3.对象中的this

     /**
         * 3.当this处在一个对象中,这个this指向的是这个对象本身
         */
        let obj = {
            a: 1,
            b: function () {
                console.log(this.a)
            }
        };
    obj.b()
    

    首先看一下打印结果


    image.png

    可以看到这里的this指向了这个obj
    接下来我们看看去this在构造函数中的指向

    这里先创建一个对象的构造函数
    function addobj(a) {
            this.a = a
            this.d = 5
            console.log(this)
        }
    先看看这里面的this指向什么,很显然指向的是window,没有new关键字在,这个函数就不是个构造函数,
    他还是一个普通的函数,跟this的第一种指向一样,他指向的也是window。
    

    接下来我们用上new关键字,来实例化一个对象

        function addobj(a) {
            console.log(this,'我是构造函数里的this')
            this.a = a
            this.d = 5
        }
        let obj = new addobj(6)
        console.log(obj,'我是构造出来的对象obj')
    
    image.png

    可以看到构造函数里的this打印出来和构造出的obj是一样的,这是为什么呢。原因就在new这个关键字中。
    new关键字做了什么:创建一个对象,把this指向这个对象,然后给这个对象赋值,最后return这个对象,所以我们let 的obj的值,其实就是new关键字创建的对象,这就很合理的解释了,为什么构造函数中打印的东西会和构造出来的obj一样。其实他们本来就是同一个对象!

    我们都知道对象的原型链指向的是构造函数的原型对象,也就是说obj.proto=>addobj.prototype。先来验证一下

        function addobj(a) {
            this.a = a
            this.d = 5
        }
        addobj.prototype = {
            b: 2,
        };
        let newobj = new addobj(1);
        console.log(newobj);
    

    上面代码中给addobj这个函数的原型prototype赋值了一个对象,我们打印看看结果


    image.png

    可以看到,obj本身已经有了构造函数中的a和d属性,并且obj的proto中还有一个b,这个b当然就是构造函数的prototype上的属性。
    那么这个时候我们看看this指向的是谁呢

        function addobj(a) {
            this.a = a
            this.d = 5
        }
        addobj.prototype = {
            b: 2,
            c: function () {
                console.log(this)
            }
        };
        // addobj.prototype.c()
        let newobj = new addobj(1);
        console.log(newobj);
        newobj.c()
    
    image.png

    可以看到,构造函数中的两个打印出来的东西还是一样的,那我们是不是可以理解为,函数中的this始终指向调用他的那个对象呢,
    再来看一段代码验证猜想

        function addobj(a) {
            this.a = a
            this.d = 5
        }
        addobj.prototype = {
            b: 2,
            c: function () {
                console.log(this)
            }
        };
        addobj.prototype.c()
        let newobj = new addobj(1);
        console.log(newobj);
        newobj.c()
    
    image.png

    我们通过addobj.prototype去调用c,这个时候this指向的不是newobj了,他指向了addobj.prototype。
    综上所述,this在对象中,指向的就是当前对象本身。

    4.简单使用一下call aplay bind
    在了解了上述知识之后,我们知道了this的指向,那在有些情况下,我们需要this不按照常规来指向,而是按照我们自己的意愿去指向,这个时候 call aplay bind 方法就派上用场了
    call:

        let obj = {
            a:2
        }
        function f1() {
            console.log(this)
        }
        f1()
        f1.call(obj)
    
    image.png

    在f1函数中打印this,直接调用f1方法和通过call去调用打印出了不一样的值,
    直接调用毋庸置疑,打印出的是window对象,因为函数中的this指向的就是window,
    而当我们通过call方法,并且传入一个对象的时候,这个时候this的指向就发生变化了,他指向了obj这个对象。这样就做到了改变this 的指向了。
    call方法还可以传入参数

        let obj = {
            a:2
        }
        function f1(...param) {
            console.log(this,param)
        }
        f1()
        f1.call(obj,1,2,3)
    
    image.png

    applay方法和call方法一样,只是在传入参数的时候call方法可以传任意形式的,而applay方法只能传入数组,

        f1.apply(obj,[1,2,3])
    

    bind方法就是给当前this绑定一个对象,但是bind方法跟其他两个不一样,他会返回一个函数,这个函数如果不主动调用,他是不会执行的

        let obj = {
            a:2
        }
        function f1(...param) {
            console.log(this,param)
        }
        f1()
        let fu = f1.bind(obj,1,2)
        fu()
    
    image.png

    如果不去调用fu的话,这个函数是不会自己执行的哦!
    以上均为个人理解,并不全面。

    相关文章

      网友评论

          本文标题:JavaScript中this的指向

          本文链接:https://www.haomeiwen.com/subject/ltbsnktx.html