工厂模式: 使用简单的函数创建对象,为对象添加属性和方法,然后返回对象。 这个模式后来被构造函数模式所取代。 缺点: 虽然解决了创建多个相似对象的问题,但没有解决对象识别的问题,还是就是方法不是每个对象共享的。
组合使用构造函数模式和原型模式: 创建自定义类型的最常见方式就是组合使用构造函数模式 和原型模式。构造函数用于定义实体的属性,而原型模式 用于定义方法和共享属性。这个混合模式还可以像构造 函数传递参数。 这种符合模式,是目前在ECMAScript中使用最广泛,认同度最高 的一种自定义对象类型方法。这是用来定义引用类型的一种默认模式。
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;
}
var person1 = createPerson ("a",17,"software engineer");
var person2 = createPerson ("b",21,"teacher");
person1.sayName ();//a
person2.sayName ();//b
alert (person1.sayName == person2.sayName);//false
构造函数模式: 可以创建自定义应用类型,可以像创建内置对象实例一样使用new操作符,解决了类型 识别的问题。 缺点: 没有做到方法多个对象共享。
function Person (name,age,job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function () {
alert (this.name);
}
}
var person1 = new Person ("a",17,"software engineer");
var person2 = new Person ("b",21,"teacher");
person1.sayName();//a
person2.sayName();//b
alert (person1.sayName == person2.sayName);//false
通过把函数定义转移到构造函数外部来解决这个问题 缺点: 在全局环境中定义的函数实际上只能被某个对象调用,否则就没有任何封装性可言。
function Person (name,age,job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
function sayName () {
alert (this.name);
}
原型模式: 我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针 指向的这个对象用途是包含可以有特定类型的所有实例共享的属性和方法。 就是通过调用构造函数而创建的那个对象实例的原型对象。 缺点: 1:省略了为构造函数传递初始化参数这个环节。 2:原型中的所有属性被很多的实例共享。这种共享对于函数很适合。对于那些包含 基本值的属性倒也可以,毕竟,通过在实例是添加一个同名属性,可以隐藏原型中的对应 的属性,但是对于引用类型来说,就不好了。 看下面例子:
function Person () {
}
Person.prototype = {
constructor:Person,
name:"a",
age :17,
job:"software",
colors:["pink","maroon"],
sayName:function () {
alert (this.name);
}
};
var person1 = new Person ();
var person2 = new Person ();
person1.colors.push ("black");
alert (person1.colors);//"pink","maroon","black"
alert (person2.colors);//"pink","maroon","black"
alert (person1.colors == person2.colors);//true
function Person () {
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 17;
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
上面共享了一个数组,可是实例一般都是有属于自己全部的属性的。 更简单的原型语法
function Person () {
}
Person.prototype = {
name:"a",
age :17,
job :"software engineer",
constructor:Person,
sayName :function () {
alert (this.name);
}
};
原型: 只有创建一个新的函数,就会根据一组特定的规则为 该函数创建一个prototype属性,这个属性指向函数的 原型对象。在默认的情况下,所有的原型对象都会自动获得 一个constructor(构造函数)属性。eg:Person.prototype.constructor 指向Person构造函数。 当调用构造函数创建一个新的实例后,该实例的内部将包含一个指针,指向构造函数的 原型对象。ECMA-262第5版中管这个指针叫[[Prototype]]。不过,要明确的一点就是, 这个连接存在于实例与构造函数的原型对象之间,而不是存在于实例与构造函数之间。 原型模式的重要性不仅体现在创建自定义类型方面,就连所有的原生的引用类型,都是 采用这种模式创建的。eg:(Object,Array,String ...)都在其构造函数的原型是定义方法。 上面Person可以用这个图表示:
function Person (name,age,job) {
this.name = name;
this.age = age;
this.job = job;
this.colors = ["pink","maroon"];
}
Person.prototype = {
constructor:Person,
sayName:function () {
alert (this.name);
}
};
var person1 = new Person ("a",17,"software engineer");
var person2 = new Person ("b",21,"teacher");
person1.colors.push("black");
alert (person1.colors);//"pink","maroon","black"
alert (person2.colors);//"pink","maroon"
alert (person1.colors == person2.colors);//false
alert (person1.sayName == person2.sayName);//true
动态原型模式: 为了达到更好的封装,可以在构造函数里初始化原型
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);
};
}
}
寄生构造函数模型: 创建一个函数,该函数的作用仅仅是封装创建对象 的代码,然后再返回新创建的对象;但是从表面上看 这个函数又很想像是典型的构造函数。 缺点: 构造函数返回的对象与构造函数或者构造函数的原型属性之间 没有关系,建议尽量不要使用该模式。
function Person (name,age,job) {
var o = new Object ();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function () {
alert (this.name);
};
return o;
}
var friend = new Person ("a",17,"teacher");
friend.sayName ();
稳妥构造函数模式:稳妥对象指的是没有公共属性,而且其方法也不引用this的对象。稳妥对象最适合在一些安全的环境中使用。与寄生构造函数不同点:1:新创建的对象的实例方法不引用this。2:不使用new操作符调用构造函数。
function Person (name,age,job) {
//创建要返回的对象
var o = new Object ();
//可以在这里定义私有的变量和函数
//添加方法
o.sayName = function () {
alert (name);
};
return o;
}
var friend = Person ("a",17,"teacher");
friend.sayName ();