JS101:Constructor Functions

EMAScript5.1规范说明书中定义了调用内置type(Object, Function, String...)构造函数可以就像调用一般函数一样.这就意味着你不仅可以用new Array(1,2),你也可以用Array(1,2)来生成一个数组, 这两种用法有什么区别呢:
当Array像普通函数一样用时与当成构造函数调用它们返回的结果是相同的,这就意味着Array(...)和调用new Array(...)是相同的。

– 15.4.1 The Array Constructor Called as a Function

当调用String(),Object()时,它们所完成的功能是进行类型转换:

var a=new String(1);
//{'0':'1'}
var b=String(1);
//'1'

Date构造函数也会执行一个数据类型的转换,但是对初学者可能造成一定的困扰为什么用不同的方式来调用会得到不同的结果:

var a=new Date(2012, 0, 1);
//Sun, 01 Jan 2012 00:00:00 GMT
Date(2012, 0, 1)
//'Sun Jun 10 2012 11:28:03 GMT+0100(BST)'

在第一行代码中,返回的是一个Date object,而在第二句代码中,则返回的是一个字符串常量。

返回对象的构造函数

在章节13.2.2,从构造函数中返回对象的行为是这样被定义的:

如果Type(result)是一个对象,那么就返回这个对象.

这就意味着我们的构造函数不一定会返回一个本类型实例化的一个对象,有可能是另外一个对象,请看下面的代码:

function Shape(){
  return{
    x:1, y:1
  }
}

Shape.prototype={
  move:function(){}
};

var shape=new Shape();
shape.move();
// 我们会得到一个错误,object没有这个方法move

这里有一种方法来检测,我们的构造函数是当成构造函数来用(new)还是当普通函数来用,请看下面的示例代码:

function Shape(){
  if(this instanceof Shape){
    //一个对象被实例化: new Shape()
  }else{
     return {
       a:'b'
     }
  }
}

Shape.prototype={
  move:function(){}
};

var shape=new Shape();
shape.move();
Shape();//返回的是{a:'b'}

jQuery也用到了上述相同的方法来实例化一个jQuery.Event对象而不需要用到new关键字:

jQuery.Event=function(src, props){
  //允许实例化一个对象而不需要用到new关键字
  if(!(this instanceof jQuery.Event)){
    return new jQuery.Event(src, props);
  }
}

结论:

如果仅仅是进行数据类型的转换可以用像调用普通函数一样的方法来调用构造函数而不需要用到new关键字,但是有一些构造函数的表现就像我们用new关键字一样的。为了避免这种因为不用new关键字而引起的bug,请记住这两种调用方式所返回的结果是不同的。

当我们自己在写构造函数的时候,我们可以创建上面代码中所提到的类似工厂方法的代码形式。它可以用来检测,我们是用new来实例化对象还是只是像调用普通函数一样来调用.

 原文地址:http://dailyjs.com/2012/06/11/js101-constructor-functions/

  

posted @ 2012-06-27 21:41  moonreplace  阅读(942)  评论(0编辑  收藏  举报