1.工厂模式
这种模式抽象了常见具体对象的过程
function createPerson(name, age, job){
var o= new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
alert(this.age);
}
return o;
}
var person1= createPerson("ad",15,"程序员");
var person2= createPerson("ad2",19,"程序员");
alert(person1.sayName == person2.sayName); //false
2.构造函数模式
构造函数可以用来创建特定类型的对象
//构造模式创建对象
function Person(name, age, job){
this.name =name;
this.age = age;
this.job =job;
this.sayName =function(){
alert(this.age);
}
}
var person3= new Person("bob",16,"程序员");
var person33= new Person("bob",16,"程序员");
// alert(person3.name );
// person3.sayName();
alert(person3.sayName == person33.sayName);//false
相比起工厂模式,Person和createPerson除了代码相同的地方之外,还存在如下不同
- 没有显式的创建对象
- 直接将属性和方法赋给this对象
- 没有return语句
因为是构造函数,所以Person开头大写
创建Person实例,必须使用new操作符
这种方式调用构造函数会经历以下4个
- 创建一个新对象
- 将构造函数的作用域赋给新对象(因此this指向了这个新对象)
- 执行构造函数中的代码(为这个对象添加属性)
- 返回新对象
1.将构造函数当做函数
//当做构造函数使用
var person2= new Person("bob",16,"程序员");
alert(person2.name );
person2.sayName();
//作为普通函数使用
Person("bob",16,"程序员"); //添加到window
window.sayName();
//在另一个对象的作用域中调用
var o = new Object();
Person.call(o,"bob",16,"程序员");
o.sayName();
2.构造函数的问题
主要问题:每个方法都要在每个实例上创建一遍
3.原型模式
创建的每一个函数都有一个prototype(原型)属性。这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定的类型的所有实例共享的属性和方法。
通俗的讲,prototype就是通过调用构造函数而创建那个对象的原型对象。
使用原型对象的好处是可以让所有对象实例共享他所包含的属性和方法。
function Persons(){
}
Persons.prototype.name='cc';
Persons.prototype.age = 29;
Persons.prototype.sayName = function(){
alert(this.name);
}
var person3 = new Persons();
var person4 = new Persons();
alert(person3.sayName ==person4.sayName); //true
当为对象实例添加一个属性时,这个属性就会屏蔽原型对象保存的同名属性,换句话说,添加这个属性只会阻止我们访问原型中的那个属性,但不会修改那个属性。即使将这个属性设为null,也只会在实例中设置这个属性,而不会恢复其指向原型的链接,不过使用delete操作符则可以完全删除实例属性。
4.组合使用构造函数模式和原型模式
创建自定义类型的最常见方式,就是组合使用函构造函数模式和原型模式。
构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性
//构造函数模式与原型模式
//构造函数模式用于定义实例属性,原型模式用于定义方法和共享属性
function Person2(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Shelby","count"];
}
Person2.prototype = {
constructor : Person2,
sayName :function(){
alert(this.name);
}
}
var person2s = new Person2('denry',20,'是');
// alert(person2s.age);
// person2s.sayName();
var person3s = new Person2('Gerg',20,'doctor');
alert(person3s.friends);
alert(person2s.friends ==person3s.friends); //false
person3s.friends.push('denry');
alert(person3s.friends);
alert(person2s.friends ==person3s.friends); //false
alert(person2s.sayName ==person3s.sayName); //true
这个例子中实例属性在构造函数中定义,共享属性constructor和sayName在原型中定义,修改person3s.friends
并不会影响到person2s.friends
,因为他们分别引用了不同的数组
5.动态原型模式
特点:把所有信息都封装在了构造函数中,而通过在构造函数中初始化原型,又保持了同时使用构造函数和原型的优点
换句话说:检查某个应该存在的方法是否有效,来决定是否需要初始化原型。
//动态原型模式
function Person3(name, age, job){
//属性
this.name = name;
this.age = age;
this.job = job;
//方法
if(typeof this.sayName!= "function"){
Person3.prototype.sayName = function(){
alert(this.name);
};
}
}
这段代码只会在初次调用调用构造函数时才会执行。