this指向的问题以及改变方法

this指向问题最核心的一句话:

哪个对象调用函数,函数里面的this就指向哪个对象

理解起来是有点抽象

下面是一些列子

1、普通函数调用

2、对象函数调用

3、构造函数调用

4、apply、call调用

5、箭头函数调用

一、普通函数调用

在非严格模式下,this的指向都是window

下面需要注意let、var不同写法的区别

先介绍下let、 var,let是块级作用域变量,写在函数中则只在函数内部有效。var申明的变量要不是全局的,要么就是函数级别的,不是块级的

这里用代码简单介绍下let、var

都是let的情况下

<script>
        let fn = function() {
            let name = 'tom'
            if (true) {
                let name = 'pig'
                console.log(name);
            }
            console.log(name);
        }
        fn()
    </script>

image-20210617210613027

先使用let后使用var

<script>
        let fn = function() {
            let name = 'tom'
            if (true) {
                var name = 'pig'
                console.log(name);
            }
            console.log(name);
        }
        fn()
    </script>

image-20210617210756205

会发现报错,因为var相当于函数级作用域,相当于一个函数作用域中有两个n的变量,var作用于整个fn,和let冲突了,let不能重复的声明,already been declared=已经被声明。

先var 后let的情况

<script>
        let fn = function() {
             var name = 'tom'
            if (true) {
                let name = 'pig'
                console.log(name);
            }
            console.log(name);
        }
        fn()
    </script>

image-20210617211119625

这里没发现报错因为先声明var再声明let是可以的

上面可以简单的对var let有个理解,方便理解下面的知识

1、使用let

 <script>
        let name = "tom"

        function fn() {
            console.log(this.name); //undefind
        }
        fn();
    </script>

这里打印出来的是undefined

2、使用var

 <script>
        var name = "tom"

        function fn() {
            console.log(this.name); //tom
        }
        fn();
    </script>

这里打印出来的是tom

区别就是上面描述的

3、使用window

 <script>
        window.name = "tom"

        function fn() {
            console.log(this.name); //tom
        }
        fn();
    </script>

打印出来的是tom

二、对象函数调用

简单的理解就是哪个函数调用,this就指向哪里

<script>
        let name = "tom"
        let obj = {
            id: 121,
            fn: function() {
                console.log(this.name);
                console.log(this.id);
            }
        }
        obj.fn()
    </script>

image-20210617211644290

这里obj调用了函数,所以this指向指向了obj,obj中只有id没有那么

这里会出现b赋值给a然后a调用,注意this指向不要搞混

 <script>
        let obj1 = {
            name: "tom"
        }
        let obj2 = {
            name: "pig",
            fn: function() {
                console.log(this.name);

            }
        }
        obj1.fn = obj2.fn
        obj1.fn()
    </script>

image-20210617212139077

再次声明:哪个函数调用this就指向哪里

三、构造函数调用

 <script>
        let fn = function() {
            this.name = "tom"
        }
        let fn1 = new fn()
        console.log(fn1.name);

        let fn2 = new fn()

        fn2.name = "pig"
        console.log(fn2.name);
    </script>

这里可以看到this指向

image-20210617214730491

这里需要注意return的出现

<script>
        let fn = function() {
            this.name = "tom"
            return {
                username: 'age'
            }
        }
        let fn1 = new fn()
        console.log(fn1);
        console.log(fn1.name);
    </script>

image-20210617214935628

这里发现return中的this指向指向的直接指向这个对象,而不是函数

四、apply和call、bind

上面介绍了this在函数中的指向问题,在现实中我们可以改变this的指向,比如apply、call、bind

apply

用法:改变函数中的this指向。

xxx.apply(对象名,数组) 就是将xxx函数中的this指向指向对象名,数组中的元素依次与元素的参数对应

function fn(a, b) {
            console.log(this);
            console.log(a + b);
        }
        fn(1, 2)
        var obj = {
            name: 'tom'
        }
        fn.apply(obj, [3, 4])

image-20210618215533051

call

用法:改变函数中的this指向问题,和apply的区别是第二个参数不为数组

xxx.call(对象名,参数1,参数2,参数3.......) 就是将xxx函数中的this指向指向对象名,参数中的元素依次与元素的参数对应

<script>
        function fn(a, b) {
            console.log(this);
            console.log(a + b);
        }
        fn(1, 2)
        var obj = {
            name: 'tom'
        }
        fn.call(obj, 3, 4)
    </script>

image-20210618215842176

bind

用法:改变函数中的this指向问题,和call写法一样,不同的地方是bind返回的是一个函数,所以我们在调用的时候在进行传参

xxx.bind(对象)(参数1,参数2......)

 <script>
        function fn(a, b) {
            console.log(this);
            console.log(a + b);
        }
        fn(1, 2)
        var obj = {
            name: 'tom'
        }
        fn.bind(obj)(3, 4)
    </script>

image-20210618220443791

五、箭头函数调用

ES6中提供的箭头函数,箭头函数中没有this,箭头函数中的this是继承外部函数的this。

<script>
        let obj = {
            name: 'tom',
            fn: function() {
                setTimeout(function() {
                    console.log(this.name)
                })
            }
        }
        obj.fn()
    </script>

这里的到的this.name为undefined,因为普通函数中的this指向的是window对象,这里window中并没有定义name,所以为空。

<script>
        let obj = {
            name: 'tom',
            fn: function() {
                setTimeout(() => {
                    console.log(this.name)
                })
            }
        }
        obj.fn()
    </script>

这里使用箭头函数,在定时器中找不到this指向会向上级查找,所以是tom

image-20210618223314055

posted @ 2021-06-18 22:34  啊方不方  阅读(105)  评论(0编辑  收藏  举报