webJ

追求自由美好的生活

JavaScript 中的几种设计模式

虽然object构造函数或对象字面量都可以用来创建单个对象,但这些方式明显有个缺点:使用同一个接口创建很多对象,会产生大量的重复代码。为了解决这个问题,人们开始使用工厂模式的一种变体

工厂模式

这种模式抽象了创建具体对象的过程

函数createPerson() 能够根据接收的参数来构建一个包含所有必要信息的Person对象,可以无数次的调用这个函数,而每次它都会返回一个包含三个属性和一个方法的对象。工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)。随着JavaScript的发展,又有一个新模式出现了。

构造函数模式

Person() 和 createPerson() 的不同之处:

  1. 没有显式的创建对象
  2. 直接将属性和方法赋给了this对象
  3. 没有return 语句

PS: 按照惯例 构造函数始终都应该以一个大写字母开头来命名。主要是区别与其他函数,因为构造函数也是函数,只不过是用来创建对象而已。

Person1 保存着Person一个不同的实例。这个对象有一个constructor(构造函数)属性,该属性指向Person,如下所示:

 

对象的constructor属性最初是用来标识对象类型的。但是,提到检测对象类型,还instanceof 操作符,要更可靠一些。

任何函数,只要通过new 操作符来调用,它就可以作为构造函数;而任何函数,如果不通过new操作符来调用,跟普通函数没区别。 如前面定义Person() 函数可以通过下列任何一种方式来调用。

?构造函数的问题

构造函数的每个方法都要在每个实例上重新创建一遍。在前面的例子中,person1和person2 都有一个sayName() 方法,但是两个方法不是同一个function的实例。

ECMAScrpit 中的函数是对象,因此每定义一个函数,也就是实例化了一个对象,从逻辑角度上讲,此时构造函数也可以这样定义

以这种函数创建函数,会导致不同的作用域链和标识符解析,因此不同实例上的同名函数是不相等的,下面例子可以证明这一点

创建两个完成同样任务的Function实例,实在是没有必要; 况且有this对象在,根本不用在执行代码前就把函数绑定到特定的对象上。因此可以通过把函数定义转移到构造函数外部来解决问题。

person1和person2 对象就共享了在全局作用域中定义的一个sayName() ?函数,可是有个问题, 在全局作用域中定义的函数实际上只能被某个对象调用,让全局作用域名不副实。还有如果对象需要定义很多个方法,就要定义很多的全局变量,这样就丝毫没有封装性可言了

原型模式

我们创建的每一个函数都有一个prototype (原型) 属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可言由特定类型的所有实例共享的属性和方法。使用原型的好处是可以让所有对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中,如下面的例子所示

与构造函数模式不同的是,这些方法是共享的

发表评论

电子邮件地址不会被公开。