一段關於JS中this應用奇葩代碼引起的思考

function DemoFunction(){
    this.init = function(){
        var func = (function(va){
        this.va = va;
        return function(){
            va += this.va;
            return va;
        }
        })(function(va1, va2){
            var va3 = va1 + va2;
            return va1;
        }(1,2));
        
        console.log(func(20));

        this.func = func;
        console.log(this.func(100));
    }
}
var a = new DemoFunction();
a.init();

首先咱們得有以下幾個概念:html

詳細解釋此段代碼this

1、首先看DemoFunction的構造函數

這是代碼的重點,第一層代碼能夠縮減爲以下:prototype

function DemoFunction(){
    this.init = function(){
        //省略代碼....
    }
}

表示爲DemoFunction的實例提供init方法(聲明:此處有誤導成份,方法應儘量放在原型連接上,也就是prototype上。),對外公開的接口。code

2、在init方法中,再次省略代碼以下:

var func = (function(va){
    this.va = va;
    return function(){
        va += this.va;
        return va;
    }
})(/*省略代碼...*/);

//省略代碼....

上面代碼介紹:htm

  • 首先定義了一個當即執行函數,並把此函數的執行結果賦值給func。對象

  • 須要注意當即執行函數中this.va=va這行代碼,因爲當即執行函數沒有調用者,因此在進入可執行上下文時,this會被賦值爲Global(瀏覽器中爲window對象)。blog

  • 更須要注意當即執行函數,返回的是一個匿名函數,也是一個閉包,在這裏必定要注意一個問題:this是在進入可執行上下文時建立的。

3、在init方法中,注意以下代碼:

var func = (function(va){
    this.va = va;
    return function(){
        va += this.va;
        return va;
    }
})(function(va1, va2){
    var va3 = va1 + va2;
    return va1;
}(1,2));
//省略代碼....

va的實際參數是一個自執行匿名函數,這個匿名函數接受了兩個參數va1,va2,但只返回了va1。以此爲據,那麼能夠肯定va的值也就爲1。接着就執行this.va=va這句代碼,因爲當前this爲window,因此參數va的值被賦值到了window的一個叫va的屬性上。

4、在init方法中,加上輸出語句:

var func = (function(va){
    this.va = va;
    return function(){
        va += this.va;
        return va;
    }
    })(function(va1, va2){
        var va3 = va1 + va2;
        return va1;
    }(1,2));
    
    console.log(func(20));

    this.func = func;
    console.log(this.func(100));
}

結果分析:

  • 第一個console.log輸出的是func(20),這裏必定要注意調用者是沒有具體指定的,此時默認的就是Global(也就是widnow對象),所以輸出爲:2

  • 第二個console.log輸出的是this.func(100),能夠看到this.func與func是指向同一個函數的引用,但此時的調用者則指定爲this,也就是當前對象的實例,所以輸出爲:NaN。緣由:this(當前對象的實例)做爲調用者,在func的函數中va += this.va這句代碼中的this是指向當前對象的實例,但當前對象的實例上是沒有va屬性的。可是va是有值的,當前值爲2了。是由於閉包把va值存到內存中了。那麼如何讓第二次獲得的值也是2呢,結果很簡單,以下:

function DemoFunction(){
        this.va = 0;
        this.init = function(){
            var func = (function(va){
            this.va = va;
            return function(){
                va += this.va;
                return va;
            }
            })(function(va1, va2){
                var va3 = va1 + va2; 
                return va1;
            }(1,2));
            console.log(func(20));
            
            this.func = func;
           
            console.log(this.func(100));
        }
    }
    var a = new DemoFunction();
    a.init();
相關文章
相關標籤/搜索