this關鍵字到底指向誰?

前言

先作一個小測試,若是所有答對了,恭喜你不用往下看了。數組

第一題

<script>
    var str = 'zhangsan';

    function demo() {
        var str = 'lisi';
        alert(this.str);
    }
    window.demo(); // ??

    var obj = {
        str: "wangwu",
        say: function() {
            alert(this.str);
        }
    }
    obj.say(); // ??

    var fun = obj.say;
    window.fun(); // ??
</script>

第二題

<script>
    var username = 'zhangsan';

    (function() {
        var username = 'lisi';
        alert(this.username); // ??
    })()

    function demo() {
        var username = 'wangwu';

        function test() {
            alert(this.username);
        }

        test(); // ??
    }
    demo();
</script>

第三題

<script>
    function Person() {
        this.username = 'zhangsan';
        this.say = function() {
            alert('我叫' + this.username);
        }
    }

    var p = new Person();
    p.say(); // ??

    var p1 = new Person();
    p1.say(); // ??
</script>

第四題

<script>
    var username = 'zhangsan';

    function demo() {
        alert(this.username)
    }

    var obj1 = {
        username: "lisi"
    };
    var obj2 = {
        username: "wangwu"
    };

    demo(); // ??
    demo(obj1); // ??
    demo(obj2); // ??
    demo.call(obj1); // ??    
    demo.apply(obj2); // ??
</script>

答案

第一題:zhangsan wangwu zhangsan
第二題:zhangsan zhangsan
第三題:我叫zhangsan 我叫zhangsan
第四題:zhangsan zhangsan zhangsan lisi wangwu
(往下看,下面有詳細解析哦)

this

  1. 指向調用函數的對象app

  2. 無對象調用函數/匿名函數自調用(this指向window)函數

  3. 經過new產生的對象測試

  4. apply/call調用this

1、指向調用函數的對象

<script>
    // this:指向調用函數的對象
    var str = 'zhangsan';

    function demo() {
        var str = 'lisi';

        //this->window
        console.log(this);
        alert(this.str);
    }
    window.demo(); // zhangsan

    var obj = {
        str: "wangwu",
        say: function() {
            // this->obj
            alert(this.str);
        }
    }
    obj.say(); // wangwu

    var fun = obj.say;
    window.fun(); // zhangsan
</script>
  • 全局函數(demo)屬於window對象的方法,window調用demo因此this就指向了window指針

  • obj調用say方法,this就指向了objcode

  • fun()是全局函數,而聲明的fun接收的是obj裏面單純的一個函數,並無調用(obj.say()纔是調用了函數),此時的fun就是一個函數(function(){alert(this.str);}),那麼當fun()調用函數的時候,this指向的就是window對象

  • 是誰調用的函數,那麼this就指向誰ip

2、無對象調用函數/匿名函數自調用->this指向window

<script>
    // 2.匿名函數自執行|匿名函數|無主函數 this->window
    var username = 'zhangsan';

    // 匿名函數自執行 this->window
    (function() {
        var username = 'lisi';
        console.log(this); // window
        alert(this.username); // zhangsan
    })()

    function demo() {
        var username = 'wangwu';

        // 無主函數 this->window
        function test() {
            // this->window
            alert(this.username);
        }

        test(); // zhangsan
    }
    demo();
</script>
  • 由於匿名函數沒有名字,因此就掛給window了io

  • test(),誰調用test那麼就指向誰。固然實驗過,它不是window調用的,也不是demo調用的,沒有人管它,那麼它就指向window。它就至關於一個沒有主人調用它,無主函數。

3、經過new產生的對象

<script>
    // 3.經過new的對象:this指向產生的對象
    // 函數
    function Person() {
        // 屬性
        this.username = 'zhangsan';
        // 方法
        this.say = function() {
            // this->p
            console.log(this); // Person對象
            alert('我叫' + this.username);
        }
    }

    // 實例化出一個對象:p就具備了username屬性和say方法
    var p = new Person();
    console.log(p); // Person對象
    console.log(p.username); // zhangsan
    p.say(); // 我叫zhangsan

    // this->p1
    var p1 = new Person();
    p1.say(); // Person對象 我叫zhangsan
</script>
  • 當咱們的函數Person裏面運用了this去寫屬性和方法這種格式,那麼就要經過new來讓屬性和方法變得有價值,經過new去運用函數裏面的屬性和方法

4、apply/call調用

首先咱們來了解下apply()/call()是個什麼東西呢?

apply()/call():最終是調用function,只不過內部的this指向了thisObj

function.call([thisObj[,arg1[, arg2[, [,.argN]]]]])
function.apply([thisObj[,argArray]])

注意:
1. 調用function函數,可是函數內的this指向thisObj(更改對象內部指針)
2. 若是thisObj沒有傳參,則默認爲全局對象
3. call()/apply()聯繫與區別
    聯繫:功能同樣,第一個參數都是thisObj
    區別:傳遞的參數若是比較多
        call()的實參就是一一列出
        apply()的實參是所有放置在第二個數組參數中

一個理解apply()/call()的實例:

<script>
    // apply()/call()
    function demo() {
        console.log(123);
    }

    // 調用函數的時候,demo.call()/demo.apply()最終調用的仍是demo()
    demo(); // 123
    demo.call(); //123
    demo.apply(); // 123
</script>

<script>
    // call()/apply()的區別:
    // call()參數單獨再call中羅列
    // apply()的參數經過數組表示
    function demo(m, n, a, b) {
        alert(m + n + a + b);
    }
    demo(1, 5, 3, 4); // 13
    demo.call(null, 1, 5, 3, 4); // 13
    demo.apply(null, [1, 5, 3, 4]); // 13
</script>

this的第四個用法實例

<script>
    // this的第四個用法:call(obj)/apply(obj):強制性的將this指向了obj
    var username = 'zhangsan';

    function demo() {
        alert(this.username)
    }

    var obj1 = {
        username: "lisi"
    };
    var obj2 = {
        username: "wangwu"
    };

    // call()/apply():打劫式的改變了this的指向
    demo(); // zhangsan
    demo(obj1); //zhangsan
    demo(obj2); //zhangsan
    demo.call(obj1); // lisi    
    demo.apply(obj2); // wangwu
</script>
  • 若是直接調用demo裏面寫的無論是obj1仍是obj2,那麼demo仍是屬於window調用的。

  • 無論你用call仍是apply最終調用的都是demo函數,但它們會強制的this指向了obj1/obj2,強制的指向了它們的第一個參數對象。

相關文章
相關標籤/搜索