Js中this指向

小吳3發表於2021-07-16

我們在初使用 JavaScript 開發的時候,多多少少會被 this 的指向搞蒙圈,弄不清楚this指向哪一個物件,但是實際上,關於 this 的指向,記住最核心的一句話: 

哪個物件呼叫函式,函式裡面的this指向哪個物件。

對this的討論,主要分以下幾種情況:

一、普通函式呼叫

1. 普通函式 this 指向window,因為一般情況下普通函式的呼叫者都是window

二、物件函式呼叫

2.物件的方法 this指向的是物件 o

var o = {
            sayHi: function() {
                console.log('物件方法的this:' + this);
            }
        }
        o.sayHi(); //this指向的是物件 o

三、建構函式呼叫

3. 建構函式 this 指向 ldh 這個例項物件 原型物件裡面的this 指向的也是 ldh這個例項物件.

var that;
        function Star(uname, age) {
            this.uname = uname,
                this.age = age,
                that = this
        };
        Star.prototype.sing = function() {
            console.log('我會唱歌');
        }
        var ldh = new Star('劉德華', 20);
        console.log(that === ldh); //ture

四、定時器函式呼叫與立即執行函式呼叫

 // 5. 定時器函式 this 指向的也是window
        window.setTimeout(function() {
            console.log('定時器的this:' + this);

        }, 1000);
        // 6. 立即執行函式 this還是指向window
        (function() {
            console.log('立即執行函式的this' + this);
        })();

五、ES6中箭頭函式的呼叫

箭頭函式不繫結this即箭頭函式沒有自己的this,如果在箭頭函式中使用this,this關鍵字將指向箭頭函式中定義位置中的this

 function fu() {
            console.log(this);
            return () => {
                console.log(this);
            }
        }
        const obj = {
            name: '張三',
            age: 20
        }
        const resfn = fu.call(obj)
        resfn()

效果如下:

六、call()和apply()與bind()呼叫

6.1 call()函式 第一個作用可以呼叫函式 第二個可以改變函式內的this 指向,但是call ()的主要作用是可以實現繼承
<script>
        var o = {
            name: 'andy',
        }
        function fu(a, b) {
            console.log(this);
            console.log(a + b);
        }
        fu.call(o, 1, 2);
        // call 第一個可以呼叫函式 第二個可以改變函式內的this 指向
        // call 的主要作用可以實現繼承
        function Father(uname, age, sex) {
            this.uname = uname;
            this.age = age;
            this.sex = sex;
        }
        function Son(uname, age, sex) {
            Father.call(this, uname, age, sex);
        }
        var son = new Son('劉德華', 18, '男');
        console.log(son);
    </script>

效果圖如下:

6.2apply()也是可以呼叫函式 ,第二個作用也可以改變函式內部的this指向,但是apply()的第二個引數必須是陣列(偽陣列)

// 2. apply()  應用 運用的意思
        var o = {
            name: 'andy'
        }

        function fu(arr) {
            console.log(this);
            console.log(arr); //列印的是字串
        }
        fu.apply(o, ['pink']);
        // 1. 也是呼叫函式 第二個可以改變函式內部的this指向
        // 2. 但是他的引數必須是陣列(偽陣列)
        // 3. apply 的主要應用 比如說我們可以利用 apply 藉助於數學內建物件求陣列最大值 
        // Math.max();
        var arr = [1, 66, 3, 99, 4];
        var max = Math.max.apply(Math, arr);
        var min = Math.min.apply(Math, arr);
        console.log(max, min);

效果如下:

6.3 bind()不會呼叫原來的函式 ,但是可以改變原來函式內部的this 指向,呼叫該函式是有返回值的,返回的是原函式改變this之後產生的新函式

 var o = {
            name: 'andy'
        };
        function fn(a, b) {
            console.log(this);
            console.log(a + b);
        };
        var f = fn.bind(o, 1, 2);
        f();

效果如下:

bind函式用的較多,如果有的函式我們不需要立即呼叫,但是又想改變這個函式內部的this指向此時用bind,比如我們有一個按鈕,當我們點選了之後,就禁用這個按鈕,3秒鐘之後開啟這個按鈕(類似於60s傳送簡訊驗證)

 var btn = document.querySelector("button");
        btn.onclick = function() {
            // var that = this;
            this.disabled = true; // 這個this 指向的是 btn 這個按鈕
            setTimeout(function() {
                    // that.disabled = false;定時器函式裡面的this 指向的是window
                    this.disabled = false; // 此時定時器函式裡面的this 指向的是btn
                }.bind(this), 3000) // 這個this 指向的是btn 這個物件
        }

七、call()和apply()與bind()總結

相同點:都可以改變this指向

不同點: call 和 apply 會呼叫函式, 並且改變函式內部this指向 ,call傳遞引數使用逗號隔開傳遞,apply傳遞第二個引數使用陣列傳遞, bind 不會呼叫函式

應用場景: call 經常做繼承, apply 經常跟陣列有關係. 比如藉助於數學物件實現陣列最大值最小值 ,bind 不呼叫函式,但是還想改變this指向. 比如改變定時器內部的this指向

好了,關於js中this的指向問題就介紹到這裡啦。如果你發現文中有錯誤的地方,還希望大佬們指正,共同進步

相關文章