1. 程式人生 > 其它 >this指向的問題以及改變方法

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>

先使用let後使用var

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

會發現報錯,因為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>

這裡沒發現報錯因為先宣告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>

這裡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>

再次宣告:哪個函式呼叫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指向

這裡需要注意return的出現

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

這裡發現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])

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>

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>

五、箭頭函式呼叫

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