Javascript中的new

一、new到底做了什么?

首先,我们来试着看一下new的实例中到底包含些什么?

 function base(){
     this.str="tong";
}

var a=new base();
console.dir(a);

在控制器中的结果如下:

我们看到其中包含str的同时,还包含着_proto_对象,上网查了一下,这个_proto_其实是构造函数的prototype。

 

接着,我们来看一下_proto_里面的东西?

我们可以看到,里面也有一个_proto对象,和上面实例中包含的_proto_是一致的

我们重点看一下其中的constructor对象,它指的是function base(),也就是我们的构造函数,但是这样说其实不准确,我们来实验一下。

        function Base(){
            this.str="tong";
        }
        Base.prototype.constructor = function Other(){ };
        var b = new Base();
        console.dir(b);

来看一下结果:

constrctor变成了Other,所以说我们之前对constructor的理解是错误的。在创建一个函数时,会自动生成对应的原型,这个原型包含一个constructor属性,使用new构造的实例,可以通过原型链查找到constructor。

 

最后,我们在来试验一下在构造函数中返回值。我们不经常这么做,但是我们也要看一下效果,来进一步分析new。

       function Base(){
            this.str="tong";
            return 1;
        }
        var a=new Base();
        console.dir(a);

结果是:

跟原来一样。

我们再来返回对象试一下:

       function Base(){
            this.str="tong";
            return [1];
        }

结果:

此时结果就不一样了,从上面的例子可以看出,如果返回的是对象,就会覆盖构造的实例。

 

我们来总结一下,new至少做了4件事:

// new Base();

// 1.创建一个空对象 obj
var obj = {};  
// 2.设置obj的__proto__为原型
obj.__proto__ = Base.prototype;  
// 3.使用obj作为上下文调用Base函数
var ret = Base.call(obj);  
// 4.如果构造函数返回的是原始值,那么这个返回值会被忽略,如果返回的是对象,就会覆盖构造的实例
// return null除外
if(typeof ret == 'object'){ return ret; } else { return obj; }

 

二、new的不足

在《Javascript语言精粹》(Javascript: The Good Parts)中,道格拉斯认为应该避免使用new关键字:

If you forget to include the new prefix when calling a constructor function, then this will not be bound to the new object. Sadly, this will be bound to the global object, so instead of augmenting your new object, you will be clobbering global variables. That is really bad. There is no compile warning, and there is no runtime warning.

大意是说在应该使用new的时候如果忘了new关键字,会引发一些问题。最重要的问题就是影响了原型查找,原型查找是沿着__proto__进行的,而任何函数都是Function的实例,一旦没用使用new,你就会发现什么属性都查找不到了,因为查找的路断了。

posted @ 2015-12-17 22:51  很好玩  阅读(2215)  评论(0编辑  收藏  举报