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();
首先我们得有如下几个概念:
执行上下文:每次当控制器转到ECMAScript可执行代码时,即会进入一个可执行上下文,参考文献:深入理解JavaScript系列(11):执行上下文(Execution Contexts)
this:this的创建是在 “进入执行上下文” 时创建的,在代码执行过程中是不可变的,参考文献:深入理解JavaScript系列(13):This? Yes,this!
自执行函数:准确来说应该叫:立即调用函数表达式。因为他声明后即执行,参考文献:深入理解JavaScript系列(4):立即调用的函数表达式
详细解释此段代码
一、首先看DemoFunction的构造函数
这是代码的重点,第一层代码可以缩减为如下:
function DemoFunction(){
this.init = function(){
//省略代码....
}
}
表示为DemoFunction的实例提供init方法(声明:此处有误导成份,方法应尽可能放在原型链接上,也就是prototype上。),对外公开的接口。
二、在init方法中,再次省略代码如下:
var func = (function(va){
this.va = va;
return function(){
va += this.va;
return va;
}
})(/*省略代码...*/);
//省略代码....
上面代码介绍:
首先定义了一个立即执行函数,并把此函数的执行结果赋值给func。
需要注意立即执行函数中this.va=va这行代码,由于立即执行函数没有调用者,所以在进入可执行上下文时,this会被赋值为Global(浏览器中为window对象)。
更需要注意立即执行函数,返回的是一个匿名函数,也是一个闭包,在这里一定要注意一个问题:this是在进入可执行上下文时创建的。
三、在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的属性上。
四、在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();
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。