this浅谈

作者: 夏日清风_期待 | 来源:发表于2017-12-08 14:01 被阅读0次

    关于js的this指向,一直以来碰到的问题还是挺多的,尤其是刚入行的时候,也是面试时屡试不爽的题型。先是ES5的this指向,现在轮到ES6中箭头函数的this了,因为开发中躺过箭头函数的坑,所以这里顺带记一下this的指向问题吧。

    ES5中,这个问题相信大家都很熟悉了,在这里主要归结为5类:
    1.函数作为普通函数调用,在非严格模式下this指向window,严格模式下this指向undefined
    2.函数作为对象的方法调用,this指向调用方法的对象
    3.使用new 构造函数创建对象,this指向构造函数内部新创建的对象
    4.上下文的方式调用(call | apply),this指向第一个参数
    5.定时器中,this指向window

    这里只举例子,就不多解释了

    1.普通函数调

    非严格模式:

    <script>
    function a() {
            console.log('结果是---',this);
        }
        a();
    </script>
    
    image.png

    严格模式下:

    <script>
        "use strict"
        function a() {
            console.log('结果是---',this);
        }
        a();
    </script>
    
    image.png
    2.函数作为对象的方法调用
    <script>
        var a = {
            name:'test',
            test:function(){
                console.log('结果是---', this);
            }
        }
        a.test()
    </script>
    
    image.png
    3.使用new 构造函数创建对象
    <script>
        function Person(name) {
            this.name = name;
        }
        var jack = new Person("Jack");
        console.log('结果是---', jack.name);
    </script>
    
    image.png
    4.上下文的方式调用(call | apply)
    <script>
    
        var obj1 = {
            name : "obj1",
            showName : function () {
                console.log('结果是---',this);
            }
        };
        var obj2 = {
            name : "obj2"
        };
        obj1.showName("憨厚","厚道");
        obj1.showName.call(obj2,"狡猾","灵活");
        obj1.showName.apply(obj2,["智商高","情商高"]);
    </script>
    
    image.png
    5.定时器中
    <script>
    
     var time1 = setInterval(function () {
         console.log('time1结果是---',this);
     },1000)
    
        var time2 = setTimeout(function () {
            console.log('time2结果是---',this);
            clearInterval(time1);
            clearTimeout(time2)
        },2000)
    </script>
    
    image.png

    阮一峰老师《# ECMAScript 6 入门》中提到的:

    箭头函数有几个使用注意点:
    
    (1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
    
    (2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
    
    (3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
    
    (4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
    

    上面四点中,第一点尤其值得注意。this对象的指向是可变的,但是在箭头函数中,它是固定的。

    怎么理解呢,举个例子

    <body>
    <button>点击</button>
    
    <script src="http://apps.bdimg.com/libs/jquery/1.10.2/jquery.min.js"></script>
    <script>
       $('button').click(()=> {
            console.log(obj);
        })
    
        var obj = () => {
            console.log(this)
        }
        
    </script>
    </body>
    
    image.png

    这个容易理解,点击时调用了obj,而obj当中的this就指向了obj本身,跟ES5一样。
    那么,将上面js中的obj对象改一下,

    var obj = {
            test: function () {
                setTimeout(() => {
                    console.log(this)
                });
            }
        }
    
    image.png

    可以看到,setTimeout里的this依然指向obj,而不是指向window,这就是箭头函数里this指向要注意的地方了。

    箭头函数当中,是没有自己的this的,它的this是继承而来;默认指向在定义它时,它所处的对象(宿主对象)。

    上个例子中,this的宿主对象是obj,那么不管在obj里使用多少次箭头函数,箭头函数中的this都会指向obj,换句话说,在obj中,this的指向是固定的,固定指向了obj。

    <body>
    <button>点击</button>
    
    <script src="http://apps.bdimg.com/libs/jquery/1.10.2/jquery.min.js"></script>
    <script>
        $('button').click(() => {
            console.log(obj);
        })
    
        var obj = {
            test: function () {
                setTimeout(() => {
                    console.log(this)
                });
            },
            test1: function () {
                setTimeout(() => {
                    console.log(this)
                })
            },
            test2: function () {
                setTimeout(() => {
                    console.log(this)
                })
            }
        }
    </script>
    </body>
    
    image.png

    如果把obj去掉,this会指向哪里呢?

    <body>
    <button>点击</button>
    
    <script src="http://apps.bdimg.com/libs/jquery/1.10.2/jquery.min.js"></script>
    <script>
        $('button').click(() => {
            console.log(this);
        })
    
    </script>
    </body>
    
    image.png

    可以看到,在没有定义的情况下,箭头函数中的this是指向window而不是执行对象button。
    可以把这种情况转换成普通函数的情况就容易理解了:在普通函数中,this指向它的直接调用者;如果找不到直接调用者,则是window。
    对于箭头函数来说,本身没有this,但是没有调用的宿主对象,那么这个时候只能继续向上指向,最后指向到window。

    相关文章

      网友评论

        本文标题:this浅谈

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