一段关于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();
相关文章
相关标签/搜索