平截奇葩Javascript代码引发的琢磨

    
今天与同一相依为命友加同事调试一段奇葩之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可实行代码时,即会进一个而实施上下文,参考文献
  • this:this的创始是在 “进入实施上下文”
    时创建的,在代码执行过程遭到是不可变的,参考文献。
  • 打实行函数:准确的话应该吃:立即调用函数表达式。因为他扬言后就实行,参考文献。

详见解释这个段子代码

一如既往、首先看DemoFunction的构造函数

即时是代码的显要,第一层代码可以减小为如下:

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

代表也DemoFunction的实例提供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对象)。
  • 双重要小心就施行函数,返回的是一个闭包,在此肯定要是注意一个题材: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又为一个这实施函数,这个就实施函数接受了少单参数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,也是出现结果的时刻到了。

  • 第一个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是有值的,他的价值吗:1,这是胡也?这便是图域链,va虽然于眼前作用域没有,但于父级(也尽管是window的意图域下)是存一个叫va的习性之。

总结

    
通过此段示例代码的分析,我们好体会到如果深入理解Javascript代码,必须使理解都深度控制他的:闭包、this、原型链(作用域链)、立即调用函数表达式、函数等概念与机理。此类概念每时每该还浸透任务一个储藏室或者框架的代码中,有矣她们开呢基本,理解以及看明白别人的Js代码就so
easy了。