理解學習this指向問題

要點

this的指向在函數定義的時候是肯定不了的,只有函數執行的時候才能肯定this到底指向誰,實際上this的最終指向的是那個調用它的對象。segmentfault

this指向的三種狀況

狀況1:若是一個函數中有this,可是它沒有被上一級的對象所調用,那麼this指向的就是window,這裏須要說明的是在js的嚴格版中this指向的不是window,而是指向調用函數的對象實例,這種函數中的this等於undefined。app

function a(){
        var user = "維他奶";
        console.log(this);//window
        console.log(this.user);//undefined
    }
    //windonw是全局對象,全部的全局變量都是對象的屬性.
    //a()<=>window.a()
    a();
    console.log(window);
    console.log(window.user);//根本沒有user這個屬性。只有一個name="";

運行結果
clipboard.png函數

嚴格模式,請參照https://segmentfault.com/a/11...
嚴格模式下定義變量必須使用var。不然報錯.
在嚴格模式下,對象的函數中的this指向調用函數的對象實例
一樣道理,能夠推斷出,在嚴格模式下,構造函數中的this指向構造函數建立的對象實例。this

"use strict";//開啓嚴格模式
    function a(){
        var user = "維他奶";
        //在嚴格模式下,對象的函數中的this指向調用函數的對象實例
        console.log(this);//a{}
        console.log(this.user);//undefined
    }
    var A = new a();

運行結果spa

clipboard.png

狀況2:若是一個函數中有this,這個函數有被上一級的對象所調用,那麼this指向的就是上一級的對象。code

var sum = {
        a:10,
        b:{
            a:12,
            fn:function(){
                console.log(this.a);//12
            }
        }
    }
    sum.b.fn();

運行結果對象

clipboard.png

狀況3:若是一個函數中有this,儘管這個函數是被最外層的對象所調用,this指向的也只是它上一級的對象.blog

var sum = {
        a:10,
        b:{
            // a:12,
            fn:function(){
                console.log(this.a);//undefined
            }
        }
    }
    sum.b.fn();

運行結果ip

clipboard.png

注意事項
儘管對象b中沒有屬性a,這個this指向的也是對象b,由於this只會指向它的上一級對象,無論這個對象中有沒有this要的東西。內存

狀況4:this永遠指向的是最後調用它的對象,也就是看它執行的時候是誰調用的,狀況4中雖然函數fn是被對象b所引用,可是在將fn賦值給變量num的時候並無執行因此最終指向的是window,這和狀況3是不同的,狀況3是直接執行了fn。

var sum = {
        a1:10,
        b:{
            a:12,
            fn:function(){
                console.log(this.a1);//undefined
                console.log(this);//window
            }
        }
    }
    var num = sum.b.fn;
    num();

運行結果

clipboard.png

構造函數的this指向:

function A(){
        this.name = "維他奶";
    }
    var a = new A();
    console.log(a.name);//維他奶

運行結果

clipboard.png

new關鍵字到底作了什麼?
(1) 建立一個新對象;
(2) 將構造函數的做用域賦給新對象(所以 this 就指向了這個新對象);原理:自動調用apply方法,將this指向這個空對象,這樣的話函數內部的this就會被這個空的對象替代。
(3) 執行構造函數中的代碼(爲這個新對象添加屬性);
(4) 返回新對象。

return 會把new建立的this覆蓋.
若是返回值是複雜數據類型,那麼this指向的就是那個返回的對象,若是返回值不是複雜數據類型那麼this仍是指向函數的實例。

function A(){
        this.name = "維他奶";
        return 1;
    }
    var a = new A();
    console.log(a.name);//維他奶

    function A(){
        this.name = "維他奶";
        return ;
    }
    var a = new A();
    console.log(a.name);//維他奶

    function A(){
        this.name = "維他奶";
        return function(){};
    }
    var a = new A();
    //傳入空函數,因此輸出一個空,而不是undefined
    console.log(a.name);//""

    function A(){
        this.name = "維他奶";
        return null;
    }
    var a = new A();
    console.log(a.name);//維他奶

簡單數據類型:string,boolean,number,undefined,null,NaN複雜數據類型: Object,Function,Array,String,Boolean,Number其中String,Boolean,Number,是自帶的封裝好的方法。簡單數據類型存放在內存的棧中,而複雜數據類型存放在內存的堆中,把地址存放在內存的棧中,先獲取地址,再讀取堆中數據。

相關文章
相關標籤/搜索