Press "Enter" to skip to content

javscript函数的new调用与普通调用中this的差异

首先看一段代码感受一下this的作用。

        place='out';
                    function where(){
                    var place='in';
                    alert(place);         //in
                    alert(this.place);    //out
                    }
                    where();

从中可以得知,place获得了函数内部的变量,而this.place则获得了外部的变量值。这是为什么呢?其实,this的作用是指向执行当前函数的外部环境对象。在这里执行where时的环境是全局环境,所以this指向global(在浏览器中是window),那么 this.place 得到的就是全局变量 place 了。
通过下面一段代码进行验证。

       place='out';
                    passer={
                        var place: 'in',
                        askWhere: function(){
                            alert(this.place);   //in
                        },
                    };
                    passer.askWhere();

这里的this在askWhere指向的函数中,函数执行的外部环境是passer对象,所以 this 指向 passer 对象,this.place 得到的也就是 in 。
那么再看下面一段代码,new 会导致函数中的 this 出现哪些不同呢?

                    function Passer(){
                        this.place = 'in';
                        this.askWhere = function(){
                            alert( this.place );    //in
                        }
                    }
                    alert(window.place);            //undefined
                    Tom = new Passer();
                    Tom.askWhere();

如果按照之前的理论分析,Passer 中的 this 指向 global ,那么this.place 应该是在全局环境中定义了place,为什么会出现window.place = undefined 的情况呢?
这里就体现出new 调用与普通调用的区别了。其实 new 操作时进行了一下几个步骤:

                1.创建一个新的对象(并把空对象的__proto__属性设置为Passer.prototype)。
                2.将构造函数的作用域赋给新对象(此时this 指向了这个新对象)。
                3.执行构造函数中的代码(通过this 为这个新对象添加属性)
                4.返回新对象。

因此这里的this 实际上并没有指向全局,而是一个新的对象。那么执行askWhere 时函数内的this 也是指向这个新的对象内部的。
如果这里的构造函数Passer 进行普通调用,结果和我们最开始的分析是相符的。
总结:在对函数进行new 调用时this 的表现的根本原因在于创建了一个新的对象并将构造函数的作用域赋给新对象,这使得this 指向了新对象。其实this 指向执行当前函数的外部环境对象的作用是一直没变的。

Be First to Comment

发表评论

电子邮件地址不会被公开。 必填项已用*标注

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax