一段奇葩Javascript代码引发的思想

    
后天与1挚友加同事调节和测试一段奇葩的javascript代码,在分析出结果后,让自家萌生了写此篇小说的想法,如有不对之处望指正,也欢迎大家一块谈谈。缩减后的js代码如下,你是或不是能纯粹验证她的输出值呢?

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可施行代码时,即会进去3个可实行上下文,参考文献
  • this:this的创建是在 “进入实践上下文”
    时创造的,在代码推行进程中是不可变的,参考文献
  • 自进行函数:准确的话应该叫:马上调用函数表达式。因为他宣称后即进行,参考文献

详见表明此段代码

一、首先看德姆oFunction的构造函数

那是代码的机要,第壹层代码能够缩短为如下:

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

代表为德姆oFunction的实例提供init方法(注解:此处有误导成分,方法应尽量放在原型链接上,也正是prototype上。),对爷爷开的接口。

二、在init方法中,再一次省略代码如下:

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

//省略代码....

代码虽短,但消息量巨大,但诸如此类省略有个别代码后,你是或不是可以清晰的见到她的层次结构。

  • 先是定义了四个立时施行函数,并把此函数的进行理并了结果赋值给func。
  • 亟需专注及时实行函数中this.va=va那行代码,由于当下实行函数未有调用者,所以在进入可实践上下文时,this会被赋值为Global(浏览器中为window对象)。
  • 更供给注意及时实施函数,再次回到的是三个闭包,在那边一定要留意1个主题素材:this是在进入可进行上下文时创立的。
  • 也正是说此段代码实施达成后,func的值应该是如此的:

    func = function(){

    va += this.va;
    return 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));
//省略代码....

   
va又为二个及时实行函数,那么些即时施行函数接受了三个参数va一,va二,但只回去了va一。以此为据,那么可以分明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));
}

ECMAScript,重中之重分析多少个console.log,也是出现结果的时候到了。

  • 第3个console.log输出的是func(20),那里一定要注意调用者是绝非实际钦命的,此时默许的就是Global(也便是widnow对象),因而输出为:二
  • 其次个console.log输出的是this.func(拾0),能够看看this.func与func是指向同二个函数的引用,但此刻的调用者则内定为this,也便是近期目的的实例,因而输出为:NaN。

        
    原因:this(当前指标的实例)作为调用者,在func的函数中va += this.va那句代码中的this是指向当前目的的实例,但眼前目的的实例上是从未va属性的。假设您调试追踪会发觉va是有值的,他的值为:一,那是干吗呢?那便是效果域链,va即使在此时此刻功用域未有,但在父级(也正是window的功力域下)是存多少个叫va的品质的。

总结

    
通过此段示例代码的辨析,大家能够体会到要深刻掌握Javascript代码,必须要领会且深度调整他的:闭包、this、原型链(功效域链)、立时调用函数表明式、函数等概念和机理。此类概念每时每该都充斥义务3个库只怕框架的代码中,有了她们做为基石,精晓和看懂外人的Js代码就so
easy了。