看了JavaScript中面向对象的一章,里面讲到关于对象创建的几种模式,在这里做一下总结。
工厂模式
直接上代码
function createPerson(name,age,job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); } return o; }
工厂模式虽解决了创建多个相似对象的问题,但却没有解决对象识别的问题(怎么知道一个对象的类型),随着JavaScript的发展,又一个模式出现了。
构造函数模式
function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); } }
相比与工厂模式,不同之处在于:
- 没有显示地创建对象
- 直接将属性和方法赋给了this对象
- 没有return语句
注意:构造函数始终以一个大写字母开头,而非构造函数则应该以一个小写字母开头。
// 当作构造函数使用(通过new操作符来调用) var person = new Person('jh',19,'Software Engineer'); person.sayName(); //'jh'
构造函数的问题:
每个方法都要在每个实例上重新创建一遍。以这种方式创建函数,会导致不同的作用域链和标识符解析,因此,不同实例上的同名函数是不相等的,以下代码可说明问题:
alert(person1.sayName == person2.sayName); //false
原型模式
function Person(){ } Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job = "Software Engineer"; Person.prototype.sayName = function(){ alert(this.name); } var person1 = new Person(); person1.sayName(); //"Nicholas" var person2 = new Person(); person2.sayName(); //"Nicholas" alert(person1.sayName == person2.sayName); //true
Tips: 使用hasOwnProperty()方法可检测一个属性是否存在于 实例 中。(原型属性不行)
要取得对象上所有可枚举的实例属性,可用ECMAScript5的Object.keys()方法,这个方法接收一个对象作为参数,返回一个包含所有可枚举属性的字符串数组
function Person(){ } Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job = "Software Engineer"; Person.prototype.sayName = function(){ alert(this.name); } var keys = Object.keys(Person.prototype); alert(keys); //"name,age,job,sayName" var p1 = new Person(); p1.name = "Rob"; p1.age = 31; var p1keys = Object.keys(p1); alert(p1keys); //"name,age"
原型对象的问题:
原型中的所有属性被实例共享,可是实例一般都是要有属于自己的全部属性的。
组合使用构造函数模式和原型模式
function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.friends = ['Shelby','Court']; } Person.prototype = { constructor: Person, sayName: function() { alert(this.name); } }
在这个例子中,实例属性都是在构造函数中定义的,而所有实例共享的属性constructor和方法则是在原型中定义的。修改一个实例中的friends属性,并不会影响另一个实例中的friends。
动态原型方法
function Person(name,age,job){ //属性 this.name = name; this.age = age; this.job = job; //方法 if(typeof this.sayName != function){ Person.prototype.sayName = function(){ alert(this.name); }; } }
注意,这里只在sayName()方法不存在的情况下,才会将它添加到原型中。
以上是几种常用的构造函数模式,应理解其中的精髓和每种模式的优点和缺点,在合适的情境下使用。
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。